diff options
Diffstat (limited to 'src/com/android')
19 files changed, 360 insertions, 204 deletions
diff --git a/src/com/android/browser/BaseUi.java b/src/com/android/browser/BaseUi.java index 5f8944f..79c3327 100644 --- a/src/com/android/browser/BaseUi.java +++ b/src/com/android/browser/BaseUi.java @@ -201,6 +201,9 @@ public class BaseUi implements UI, WebViewFactory { if (mActiveTabsPage != null) { mUiController.removeActiveTabsPage(true); } + if (isCustomViewShowing()) { + onHideCustomView(); + } cancelStopToast(); mActivityPaused = true; } @@ -427,6 +430,24 @@ public class BaseUi implements UI, WebViewFactory { mainView.setEmbeddedTitleBar(null); } + @Override + public void onSetWebView(Tab tab, WebView webView) { + View container = tab.getViewContainer(); + if (container == null) { + // The tab consists of a container view, which contains the main + // WebView, as well as any other UI elements associated with the tab. + container = mActivity.getLayoutInflater().inflate(R.layout.tab, + null); + tab.setViewContainer(container); + } + if (tab.getWebView() != webView) { + // Just remove the old one. + FrameLayout wrapper = + (FrameLayout) container.findViewById(R.id.webview_wrapper); + wrapper.removeView(tab.getWebView()); + } + } + /** * create a sub window container and webview for the tab * Note: this methods operates through side-effects for now diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java index 9844547..a8c393a 100644 --- a/src/com/android/browser/BrowserActivity.java +++ b/src/com/android/browser/BrowserActivity.java @@ -16,6 +16,8 @@ package com.android.browser; +import com.google.common.annotations.VisibleForTesting; + import android.app.Activity; import android.content.Intent; import android.content.res.Configuration; @@ -95,16 +97,11 @@ public class BrowserActivity extends Activity { mController.start(icicle, getIntent()); } + @VisibleForTesting Controller getController() { return mController; } - // TODO: this is here for the test classes - // remove once tests are fixed - TabControl getTabControl() { - return mController.getTabControl(); - } - @Override protected void onNewIntent(Intent intent) { mController.handleNewIntent(intent); diff --git a/src/com/android/browser/BrowserBookmarksPage.java b/src/com/android/browser/BrowserBookmarksPage.java index 4887f3f..74385f9 100644 --- a/src/com/android/browser/BrowserBookmarksPage.java +++ b/src/com/android/browser/BrowserBookmarksPage.java @@ -357,8 +357,6 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte } BookmarkItem header = new BookmarkItem(activity); populateBookmarkItem(cursor, header, isFolder); - new LookupBookmarkCount(getActivity(), header) - .execute(cursor.getLong(BookmarksLoader.COLUMN_INDEX_ID)); menu.setHeaderView(header); int count = menu.size(); @@ -374,6 +372,8 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_folder); item.setFavicon(bitmap); + new LookupBookmarkCount(getActivity(), item) + .execute(cursor.getLong(BookmarksLoader.COLUMN_INDEX_ID)); } else { String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL); item.setUrl(url); diff --git a/src/com/android/browser/BrowserHistoryPage.java b/src/com/android/browser/BrowserHistoryPage.java index a3ce0b4..5cd9545 100644 --- a/src/com/android/browser/BrowserHistoryPage.java +++ b/src/com/android/browser/BrowserHistoryPage.java @@ -366,7 +366,10 @@ public class BrowserHistoryPage extends Fragment mMostVisited.close(); } mMostVisited = cursor; - mMostVisited.registerDataSetObserver(mDataSetObserver); + if (mMostVisited != null) { + mMostVisited.registerDataSetObserver(mDataSetObserver); + } + notifyDataSetChanged(); } @Override diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java index acd76dd..75dd913 100644 --- a/src/com/android/browser/Controller.java +++ b/src/com/android/browser/Controller.java @@ -317,6 +317,11 @@ public class Controller } @Override + public void onSetWebView(Tab tab, WebView view) { + mUi.onSetWebView(tab, view); + } + + @Override public void createSubWindow(Tab tab) { endActionMode(); WebView mainView = tab.getWebView(); @@ -488,6 +493,22 @@ public class Controller } + @Override + public void shareCurrentPage() { + shareCurrentPage(mTabControl.getCurrentTab()); + } + + private void shareCurrentPage(Tab tab) { + if (tab != null) { + tab.populatePickerData(); + sharePage(mActivity, tab.getTitle(), + tab.getUrl(), tab.getFavicon(), + createScreenshot(tab.getWebView(), + getDesiredThumbnailWidth(mActivity), + getDesiredThumbnailHeight(mActivity))); + } + } + /** * Share a page, providing the title, url, favicon, and a screenshot. Uses * an {@link Intent} to launch the Activity chooser. @@ -543,13 +564,16 @@ public class Controller Log.e(LOGTAG, "BrowserActivity is already paused."); return; } - mTabControl.pauseCurrentTab(); + CookieManager.getInstance().flushCookieStore(); mActivityPaused = true; - if (mTabControl.getCurrentIndex() >= 0 && - !pauseWebViewTimers(mActivityPaused)) { - mWakeLock.acquire(); - mHandler.sendMessageDelayed(mHandler - .obtainMessage(RELEASE_WAKELOCK), WAKELOCK_TIMEOUT); + Tab tab = mTabControl.getCurrentTab(); + if (tab != null) { + tab.pause(); + if (!pauseWebViewTimers(tab)) { + mWakeLock.acquire(); + mHandler.sendMessageDelayed(mHandler + .obtainMessage(RELEASE_WAKELOCK), WAKELOCK_TIMEOUT); + } } mUi.onPause(); mNetworkHandler.onPause(); @@ -575,10 +599,12 @@ public class Controller Log.e(LOGTAG, "BrowserActivity is already resumed."); return; } - mTabControl.resumeCurrentTab(); mActivityPaused = false; - resumeWebViewTimers(); - + Tab current = mTabControl.getCurrentTab(); + if (current != null) { + current.resume(); + resumeWebViewTimers(current); + } if (mWakeLock.isHeld()) { mHandler.removeMessages(RELEASE_WAKELOCK); mWakeLock.release(); @@ -588,9 +614,11 @@ public class Controller WebView.enablePlatformNotifications(); } - private void resumeWebViewTimers() { - Tab tab = mTabControl.getCurrentTab(); - if (tab == null) return; // monkey can trigger this + /** + * resume all WebView timers using the WebView instance of the given tab + * @param tab guaranteed non-null + */ + private void resumeWebViewTimers(Tab tab) { boolean inLoad = tab.inPageLoad(); if ((!mActivityPaused && !inLoad) || (mActivityPaused && inLoad)) { CookieSyncManager.getInstance().startSync(); @@ -601,19 +629,23 @@ public class Controller } } - private boolean pauseWebViewTimers(boolean activityPaused) { - Tab tab = mTabControl.getCurrentTab(); - boolean inLoad = tab.inPageLoad(); - if (activityPaused && !inLoad) { + /** + * Pause all WebView timers using the WebView of the given tab + * @param tab + * @return true if the timers are paused or tab is null + */ + private boolean pauseWebViewTimers(Tab tab) { + if (tab == null) { + return true; + } else if (!tab.inPageLoad()) { CookieSyncManager.getInstance().stopSync(); WebView w = getCurrentWebView(); if (w != null) { w.pauseTimers(); } return true; - } else { - return false; } + return false; } void onDestroy() { @@ -708,7 +740,7 @@ public class Controller // to start the timer. As we won't switch tabs while an activity is in // pause state, we can ensure calling resume and pause in pair. if (mActivityPaused) { - resumeWebViewTimers(); + resumeWebViewTimers(tab); } mLoadStopped = false; if (!mNetworkHandler.isNetworkUp()) { @@ -749,7 +781,7 @@ public class Controller } // pause the WebView timer and release the wake lock if it is finished // while BrowserActivity is in pause state. - if (mActivityPaused && pauseWebViewTimers(mActivityPaused)) { + if (mActivityPaused && pauseWebViewTimers(tab)) { if (mWakeLock.isHeld()) { mHandler.removeMessages(RELEASE_WAKELOCK); mWakeLock.release(); @@ -1565,12 +1597,7 @@ public class Controller mCanChord = false; return false; } - currentTab.populatePickerData(); - sharePage(mActivity, currentTab.getTitle(), - currentTab.getUrl(), currentTab.getFavicon(), - createScreenshot(currentTab.getWebView(), - getDesiredThumbnailWidth(mActivity), - getDesiredThumbnailHeight(mActivity))); + shareCurrentPage(currentTab); break; case R.id.dump_nav_menu_id: @@ -2312,7 +2339,7 @@ public class Controller // force the tab's inLoad() to be false as we are going to // either finish the activity or remove the tab. This will // ensure pauseWebViewTimers() taking action. - mTabControl.getCurrentTab().clearInPageLoad(); + current.clearInPageLoad(); if (mTabControl.getTabCount() == 1) { mActivity.finish(); return; @@ -2321,7 +2348,7 @@ public class Controller Log.e(LOGTAG, "BrowserActivity is already paused " + "while handing goBackOnePageOrQuit."); } - pauseWebViewTimers(true); + pauseWebViewTimers(current); removeTab(current); } /* diff --git a/src/com/android/browser/Tab.java b/src/com/android/browser/Tab.java index a048c2d..8a3bc27 100644 --- a/src/com/android/browser/Tab.java +++ b/src/com/android/browser/Tab.java @@ -85,7 +85,7 @@ class Tab { // The Geolocation permissions prompt private GeolocationPermissionsPrompt mGeolocationPermissionsPrompt; // Main WebView wrapper - private LinearLayout mContainer; + private View mContainer; // Main WebView private WebView mMainView; // Subwindow container @@ -128,8 +128,6 @@ class Tab { // the lock icon type and previous lock icon type for the tab private int mLockIconType; private int mPrevLockIconType; - // Inflation service for making subwindows. - private final LayoutInflater mInflateService; // The listener that gets invoked when a download is started from the // mMainView private final DownloadListener mDownloadListener; @@ -497,8 +495,10 @@ class Tab { @Override public void onPageFinished(WebView view, String url) { - LogTag.logPageFinishedLoading( - url, SystemClock.uptimeMillis() - mLoadStartTime); + if (!isPrivateBrowsingEnabled()) { + LogTag.logPageFinishedLoading( + url, SystemClock.uptimeMillis() - mLoadStartTime); + } mInPageLoad = false; mWebViewController.onPageFinished(Tab.this, url); @@ -1203,11 +1203,6 @@ class Tab { mInPageLoad = false; mInForeground = false; - mInflateService = LayoutInflater.from(mActivity); - - // The tab consists of a container view, which contains the main - // WebView, as well as any other UI elements associated with the tab. - mContainer = (LinearLayout) mInflateService.inflate(R.layout.tab, null); mDownloadListener = new DownloadListener() { public void onDownloadStart(String url, String userAgent, @@ -1244,16 +1239,14 @@ class Tab { if (mMainView == w) { return; } + // If the WebView is changing, the page will be reloaded, so any ongoing // Geolocation permission requests are void. if (mGeolocationPermissionsPrompt != null) { mGeolocationPermissionsPrompt.hide(); } - // Just remove the old one. - FrameLayout wrapper = - (FrameLayout) mContainer.findViewById(R.id.webview_wrapper); - wrapper.removeView(mMainView); + mWebViewController.onSetWebView(this, w); // set the new one mMainView = w; @@ -1449,6 +1442,10 @@ class Tab { return mMainView; } + void setViewContainer(View container) { + mContainer = container; + } + View getViewContainer() { return mContainer; } diff --git a/src/com/android/browser/TabControl.java b/src/com/android/browser/TabControl.java index 2d90d23..9e669ce 100644 --- a/src/com/android/browser/TabControl.java +++ b/src/com/android/browser/TabControl.java @@ -600,20 +600,6 @@ class TabControl { return setCurrentTab(newTab, false); } - void pauseCurrentTab() { - Tab t = getCurrentTab(); - if (t != null) { - t.pause(); - } - } - - void resumeCurrentTab() { - Tab t = getCurrentTab(); - if (t != null) { - t.resume(); - } - } - /** * If force is true, this method skips the check for newTab == current. */ diff --git a/src/com/android/browser/TitleBarXLarge.java b/src/com/android/browser/TitleBarXLarge.java index 7e54710..0aa09db 100644 --- a/src/com/android/browser/TitleBarXLarge.java +++ b/src/com/android/browser/TitleBarXLarge.java @@ -26,12 +26,9 @@ import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.text.TextUtils; -import android.view.ContextMenu; import android.view.LayoutInflater; -import android.view.MenuInflater; import android.view.View; import android.view.View.OnClickListener; -import android.view.View.OnFocusChangeListener; import android.widget.ImageView; import android.widget.TextView; @@ -39,11 +36,10 @@ import android.widget.TextView; * tabbed title bar for xlarge screen browser */ public class TitleBarXLarge extends TitleBarBase - implements UrlInputListener, OnClickListener, OnFocusChangeListener { + implements UrlInputListener, OnClickListener { private static final int PROGRESS_MAX = 100; - private Activity mActivity; private UiController mUiController; private Drawable mStopDrawable; @@ -67,7 +63,6 @@ public class TitleBarXLarge extends TitleBarBase public TitleBarXLarge(Activity activity, UiController controller) { super(activity); - mActivity = activity; mUiController = controller; Resources resources = activity.getResources(); mStopDrawable = resources.getDrawable(R.drawable.ic_stop_normal); @@ -106,25 +101,15 @@ public class TitleBarXLarge extends TitleBarBase mGoButton.setOnClickListener(this); mClearButton.setOnClickListener(this); mUrlFocused.setUrlInputListener(this); - mUrlUnfocused.setOnFocusChangeListener(this); mUrlFocused.setContainer(mFocusContainer); + mUrlFocused.setController(mUiController); mUnfocusContainer.setOnClickListener(this); } - public void onFocusChange(View v, boolean hasFocus) { - if (hasFocus) { - setUrlMode(true); - mUrlFocused.selectAll(); - mUrlFocused.requestFocus(); - mUrlFocused.setDropDownWidth(mUnfocusContainer.getWidth()); - mUrlFocused.setDropDownHorizontalOffset(-mUrlFocused.getLeft()); - } - } - @Override public void onClick(View v) { if (mUnfocusContainer == v) { - mUrlUnfocused.requestFocus(); + setUrlMode(true); } else if (mBackButton == v) { mUiController.getCurrentTopWebView().goBack(); } else if (mForwardButton == v) { @@ -190,6 +175,10 @@ public class TitleBarXLarge extends TitleBarBase private void setUrlMode(boolean focused) { swapUrlContainer(focused); if (focused) { + mUrlFocused.selectAll(); + mUrlFocused.requestFocus(); + mUrlFocused.setDropDownWidth(mUnfocusContainer.getWidth()); + mUrlFocused.setDropDownHorizontalOffset(-mUrlFocused.getLeft()); mSearchButton.setVisibility(View.GONE); mGoButton.setVisibility(View.VISIBLE); } else { @@ -203,13 +192,6 @@ public class TitleBarXLarge extends TitleBarBase mFocusContainer.setVisibility(focus ? View.VISIBLE : View.GONE); } - @Override - public void createContextMenu(ContextMenu menu) { - MenuInflater inflater = mActivity.getMenuInflater(); - inflater.inflate(R.menu.title_context, menu); - mActivity.onCreateContextMenu(menu, this, null); - } - private void search() { setDisplayTitle(""); mUrlUnfocused.requestFocus(); diff --git a/src/com/android/browser/UI.java b/src/com/android/browser/UI.java index 3a8a5cd..e7f67f2 100644 --- a/src/com/android/browser/UI.java +++ b/src/com/android/browser/UI.java @@ -58,6 +58,8 @@ public interface UI extends ScrollListener { public void attachTab(Tab tab); + public void onSetWebView(Tab tab, WebView view); + public void createSubWindow(Tab tab, WebView subWebView); public void attachSubWindow(View subContainer); diff --git a/src/com/android/browser/UiController.java b/src/com/android/browser/UiController.java index dffebba..c74d74e 100644 --- a/src/com/android/browser/UiController.java +++ b/src/com/android/browser/UiController.java @@ -75,4 +75,6 @@ public interface UiController extends BookmarksHistoryCallbacks { void endActionMode(); + void shareCurrentPage(); + } diff --git a/src/com/android/browser/UrlInputView.java b/src/com/android/browser/UrlInputView.java index 2e29f26..a4c2be3 100644 --- a/src/com/android/browser/UrlInputView.java +++ b/src/com/android/browser/UrlInputView.java @@ -20,8 +20,8 @@ import com.android.browser.SuggestionsAdapter.CompletionListener; import android.content.Context; import android.content.res.Configuration; +import android.text.TextUtils; import android.util.AttributeSet; -import android.view.ActionMode; import android.view.KeyEvent; import android.view.View; import android.view.View.OnFocusChangeListener; @@ -35,7 +35,8 @@ import android.widget.TextView.OnEditorActionListener; * handling suggestions */ public class UrlInputView extends AutoCompleteTextView - implements OnFocusChangeListener, OnEditorActionListener, CompletionListener { + implements OnFocusChangeListener, OnEditorActionListener, + CompletionListener { private UrlInputListener mListener; private InputMethodManager mInputManager; @@ -65,11 +66,17 @@ public class UrlInputView extends AutoCompleteTextView super.setOnFocusChangeListener(this); mAdapter = new SuggestionsAdapter(ctx, this); setAdapter(mAdapter); - setSelectAllOnFocus(false); + setSelectAllOnFocus(true); onConfigurationChanged(ctx.getResources().getConfiguration()); setThreshold(1); } + void setController(UiController controller) { + UrlSelectionActionMode urlSelectionMode + = new UrlSelectionActionMode(controller); + setCustomSelectionActionModeCallback(urlSelectionMode); + } + void setContainer(View container) { mContainer = container; } @@ -108,12 +115,6 @@ public class UrlInputView extends AutoCompleteTextView } @Override - public ActionMode startActionMode(ActionMode.Callback callback) { - // suppress selection action mode - return null; - } - - @Override public void setOnFocusChangeListener(OnFocusChangeListener focusListener) { mWrappedFocusListener = focusListener; } @@ -148,7 +149,7 @@ public class UrlInputView extends AutoCompleteTextView this.dismissDropDown(); this.setSelection(0,0); mInputManager.hideSoftInputFromWindow(getWindowToken(), 0); - if (url == null) { + if (TextUtils.isEmpty(url)) { mListener.onDismiss(); } else { mListener.onAction(url, extra); diff --git a/src/com/android/browser/UrlSelectionActionMode.java b/src/com/android/browser/UrlSelectionActionMode.java new file mode 100644 index 0000000..5636388 --- /dev/null +++ b/src/com/android/browser/UrlSelectionActionMode.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2010 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.view.ActionMode; +import android.view.Menu; +import android.view.MenuItem; + +public class UrlSelectionActionMode implements ActionMode.Callback { + + private UiController mUiController; + + public UrlSelectionActionMode(UiController controller) { + mUiController = controller; + } + + // ActionMode.Callback implementation + + @Override + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + mode.getMenuInflater().inflate(R.menu.url_selection, menu); + return true; + } + + @Override + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + switch (item.getItemId()) { + case R.id.share: + mUiController.shareCurrentPage(); + mode.finish(); + break; + default: + return false; + } + return true; + } + + @Override + public void onDestroyActionMode(ActionMode mode) { + } + + @Override + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + return true; + } + +} diff --git a/src/com/android/browser/WebStorageSizeManager.java b/src/com/android/browser/WebStorageSizeManager.java index dcf2f8b..5f76f72 100644 --- a/src/com/android/browser/WebStorageSizeManager.java +++ b/src/com/android/browser/WebStorageSizeManager.java @@ -16,17 +16,19 @@ package com.android.browser; +import com.android.browser.preferences.WebsiteSettingsFragment; + import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.os.StatFs; +import android.preference.PreferenceActivity; import android.util.Log; import android.webkit.WebStorage; import java.io.File; -import java.util.Set; /** @@ -82,7 +84,7 @@ import java.util.Set; * the user can free some of the Web storage space by deleting all the data used * by an origin. */ -class WebStorageSizeManager { +public class WebStorageSizeManager { // Logging flags. private final static boolean LOGV_ENABLED = com.android.browser.Browser.LOGV_ENABLED; private final static boolean LOGD_ENABLED = com.android.browser.Browser.LOGD_ENABLED; @@ -346,7 +348,7 @@ class WebStorageSizeManager { // Reset the notification time; we use this iff the user // use clear all; we reset it to some time in the future instead // of just setting it to -1, as the clear all method is asynchronous - static void resetLastOutOfSpaceNotificationTime() { + public static void resetLastOutOfSpaceNotificationTime() { mLastOutOfSpaceNotificationTime = System.currentTimeMillis() - NOTIFICATION_INTERVAL + RESET_NOTIFICATION_INTERVAL; } @@ -403,7 +405,9 @@ class WebStorageSizeManager { CharSequence text = mContext.getString( R.string.webstorage_outofspace_notification_text); long when = System.currentTimeMillis(); - Intent intent = new Intent(mContext, WebsiteSettingsActivity.class); + Intent intent = new Intent(mContext, BrowserPreferencesPage.class); + intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT, + WebsiteSettingsFragment.class.getName()); PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0); Notification notification = new Notification(icon, title, when); diff --git a/src/com/android/browser/WebViewController.java b/src/com/android/browser/WebViewController.java index eeeee18..11a6959 100644 --- a/src/com/android/browser/WebViewController.java +++ b/src/com/android/browser/WebViewController.java @@ -42,6 +42,8 @@ public interface WebViewController { WebViewFactory getWebViewFactory(); + void onSetWebView(Tab tab, WebView view); + void createSubWindow(Tab tab); void onPageStarted(Tab tab, WebView view, String url, Bitmap favicon); diff --git a/src/com/android/browser/preferences/AdvancedPreferencesFragment.java b/src/com/android/browser/preferences/AdvancedPreferencesFragment.java index 59b6ce1..952e04a 100644 --- a/src/com/android/browser/preferences/AdvancedPreferencesFragment.java +++ b/src/com/android/browser/preferences/AdvancedPreferencesFragment.java @@ -18,9 +18,7 @@ package com.android.browser.preferences; import com.android.browser.BrowserSettings; import com.android.browser.R; -import com.android.browser.WebsiteSettingsActivity; -import android.content.Intent; import android.os.Bundle; import android.preference.Preference; import android.preference.PreferenceFragment; @@ -44,8 +42,7 @@ public class AdvancedPreferencesFragment extends PreferenceFragment PreferenceScreen websiteSettings = (PreferenceScreen) findPreference( BrowserSettings.PREF_WEBSITE_SETTINGS); - Intent intent = new Intent(getActivity(), WebsiteSettingsActivity.class); - websiteSettings.setIntent(intent); + websiteSettings.setFragment(WebsiteSettingsFragment.class.getName()); } /* diff --git a/src/com/android/browser/preferences/PersonalPreferencesFragment.java b/src/com/android/browser/preferences/PersonalPreferencesFragment.java index a0c8ea0..0620df2 100644 --- a/src/com/android/browser/preferences/PersonalPreferencesFragment.java +++ b/src/com/android/browser/preferences/PersonalPreferencesFragment.java @@ -81,14 +81,14 @@ public class PersonalPreferencesFragment extends PreferenceFragment refreshUi(context); } - private class GetAccountsTask extends AsyncTask<Void, Void, Void> { + private class GetAccountsTask extends AsyncTask<Void, Void, String> { private Context mContext; GetAccountsTask(Context ctx) { mContext = ctx; } - protected Void doInBackground(Void... unused) { + protected String doInBackground(Void... unused) { AccountManager am = (AccountManager) mContext.getSystemService(Context.ACCOUNT_SERVICE); Account[] accounts = am.getAccountsByType("com.google"); if (accounts == null || accounts.length == 0) { @@ -97,26 +97,34 @@ public class PersonalPreferencesFragment extends PreferenceFragment getPreferenceScreen().removePreference(mChromeSync); } } else { + // Google accounts are present. SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext); Bundle args = mChromeSync.getExtras(); args.putParcelableArray("accounts", accounts); mEnabled = BrowserContract.Settings.isSyncEnabled(mContext); + mChromeSync.setOnPreferenceClickListener(PersonalPreferencesFragment.this); + if (!mEnabled) { - // Google accounts are present, but Chrome sync isn't enabled yet. // Setup a link to the enable wizard - mChromeSync.setSummary(R.string.pref_personal_sync_with_chrome_summary); + return mContext.getResources().getString( + R.string.pref_personal_sync_with_chrome_summary); } else { // Chrome sync is enabled, setup a link to account switcher - String accountName = prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_NAME, - null); - mChromeSync.setSummary(accountName); + String accountName = prefs.getString( + BrowserBookmarksPage.PREF_ACCOUNT_NAME, null); args.putString("curAccount", accountName); + return accountName; } - mChromeSync.setOnPreferenceClickListener(PersonalPreferencesFragment.this); } return null; } + + protected void onPostExecute(String summary) { + if (summary != null) { + mChromeSync.setSummary(summary); + } + } } void refreshUi(Context context) { diff --git a/src/com/android/browser/WebsiteSettingsActivity.java b/src/com/android/browser/preferences/WebsiteSettingsFragment.java index 95f8fb0..1965ffe 100644 --- a/src/com/android/browser/WebsiteSettingsActivity.java +++ b/src/com/android/browser/preferences/WebsiteSettingsFragment.java @@ -14,56 +14,62 @@ * limitations under the License. */ -package com.android.browser; +package com.android.browser.preferences; + +import com.android.browser.R; +import com.android.browser.WebStorageSizeManager; import android.app.AlertDialog; -import android.app.ListActivity; +import android.app.FragmentTransaction; +import android.app.ListFragment; import android.content.Context; import android.content.DialogInterface; +import android.content.res.Resources; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; +import android.preference.PreferenceActivity; +import android.preference.PreferenceFragment; import android.provider.BrowserContract.Bookmarks; import android.util.Log; -import android.view.KeyEvent; import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; +import android.view.View.OnClickListener; import android.view.ViewGroup; import android.webkit.GeolocationPermissions; import android.webkit.ValueCallback; -import android.webkit.WebIconDatabase; import android.webkit.WebStorage; -import android.widget.ArrayAdapter; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; +import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.TextView; +import java.io.Serializable; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; -import java.util.Vector; /** * Manage the settings for an origin. * We use it to keep track of the 'HTML5' settings, i.e. database (webstorage) * and Geolocation. */ -public class WebsiteSettingsActivity extends ListActivity { +public class WebsiteSettingsFragment extends ListFragment implements OnClickListener { + private static final String EXTRA_SITE = "site"; private String LOGTAG = "WebsiteSettingsActivity"; private static String sMBStored = null; private SiteAdapter mAdapter = null; + private Site mSite = null; - static class Site { + static class Site implements Serializable { private String mOrigin; private String mTitle; private Bitmap mIcon; @@ -169,6 +175,10 @@ public class WebsiteSettingsActivity extends ListActivity { private Site mCurrentSite; public SiteAdapter(Context context, int rsc) { + this(context, rsc, null); + } + + public SiteAdapter(Context context, int rsc, Site site) { super(context, rsc); mResource = rsc; mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); @@ -184,7 +194,10 @@ public class WebsiteSettingsActivity extends ListActivity { R.drawable.ic_list_gps_on); mLocationDisallowedIcon = BitmapFactory.decodeResource(getResources(), R.drawable.ic_list_gps_denied); - askForOrigins(); + mCurrentSite = site; + if (mCurrentSite == null) { + askForOrigins(); + } } /** @@ -409,6 +422,7 @@ public class WebsiteSettingsActivity extends ListActivity { } } + @Override public View getView(int position, View convertView, ViewGroup parent) { View view; final TextView title; @@ -434,7 +448,6 @@ public class WebsiteSettingsActivity extends ListActivity { locationIcon.setVisibility(View.GONE); if (mCurrentSite == null) { - setTitle(getString(R.string.pref_extras_website_settings)); Site site = getItem(position); title.setText(site.getPrettyTitle()); @@ -494,7 +507,6 @@ public class WebsiteSettingsActivity extends ListActivity { locationIcon.setVisibility(View.GONE); usageIcon.setVisibility(View.GONE); featureIcon.setVisibility(View.VISIBLE); - setTitle(mCurrentSite.getPrettyTitle()); String origin = mCurrentSite.getOrigin(); switch (mCurrentSite.getFeatureByIndex(position)) { case Site.FEATURE_WEB_STORAGE: @@ -551,7 +563,7 @@ public class WebsiteSettingsActivity extends ListActivity { // origins list. mCurrentSite.removeFeature(Site.FEATURE_WEB_STORAGE); if (mCurrentSite.getFeatureCount() == 0) { - mCurrentSite = null; + finish(); } askForOrigins(); notifyDataSetChanged(); @@ -570,7 +582,7 @@ public class WebsiteSettingsActivity extends ListActivity { GeolocationPermissions.getInstance().clear(mCurrentSite.getOrigin()); mCurrentSite.removeFeature(Site.FEATURE_GEOLOCATION); if (mCurrentSite.getFeatureCount() == 0) { - mCurrentSite = null; + finish(); } askForOrigins(); notifyDataSetChanged(); @@ -581,8 +593,14 @@ public class WebsiteSettingsActivity extends ListActivity { break; } } else { - mCurrentSite = (Site) view.getTag(); - notifyDataSetChanged(); + Site site = (Site) view.getTag(); + PreferenceActivity activity = (PreferenceActivity) getActivity(); + if (activity != null) { + Bundle args = new Bundle(); + args.putSerializable(EXTRA_SITE, site); + activity.startPreferencePanel(WebsiteSettingsFragment.class.getName(), args, 0, + site.getPrettyTitle(), null, 0); + } } } @@ -591,67 +609,64 @@ public class WebsiteSettingsActivity extends ListActivity { } } - /** - * Intercepts the back key to immediately notify - * NativeDialog that we are done. - */ - public boolean dispatchKeyEvent(KeyEvent event) { - if ((event.getKeyCode() == KeyEvent.KEYCODE_BACK) - && (event.getAction() == KeyEvent.ACTION_DOWN)) { - if ((mAdapter != null) && (mAdapter.backKeyPressed())){ - return true; // event consumed - } + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.website_settings, container, false); + Bundle args = getArguments(); + if (args != null) { + mSite = (Site) args.getSerializable(EXTRA_SITE); + } + if (mSite == null) { + View clear = view.findViewById(R.id.clear_all_button); + clear.setVisibility(View.VISIBLE); + clear.setOnClickListener(this); } - return super.dispatchKeyEvent(event); + return view; } @Override - protected void onCreate(Bundle icicle) { - super.onCreate(icicle); + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); if (sMBStored == null) { sMBStored = getString(R.string.webstorage_origin_summary_mb_stored); } - mAdapter = new SiteAdapter(this, R.layout.website_settings_row); - setListAdapter(mAdapter); + mAdapter = new SiteAdapter(getActivity(), R.layout.website_settings_row); + if (mSite != null) { + mAdapter.mCurrentSite = mSite; + } + getListView().setAdapter(mAdapter); getListView().setOnItemClickListener(mAdapter); } - @Override - public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.websitesettings, menu); - return true; - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - // If we are not on the sites list (rather on the page for a specific site) or - // we aren't listing any sites hide the clear all button (and hence the menu). - return mAdapter.currentSite() == null && mAdapter.getCount() > 0; + private void finish() { + PreferenceActivity activity = (PreferenceActivity) getActivity(); + if (activity != null) { + activity.finishPreferencePanel(this, 0, null); + } } @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.website_settings_menu_clear_all: - // Show the prompt to clear all origins of their data and geolocation permissions. - new AlertDialog.Builder(this) - .setTitle(R.string.website_settings_clear_all_dialog_title) - .setMessage(R.string.website_settings_clear_all_dialog_message) - .setPositiveButton(R.string.website_settings_clear_all_dialog_ok_button, - new AlertDialog.OnClickListener() { - public void onClick(DialogInterface dlg, int which) { - WebStorage.getInstance().deleteAllData(); - GeolocationPermissions.getInstance().clearAll(); - WebStorageSizeManager.resetLastOutOfSpaceNotificationTime(); - mAdapter.askForOrigins(); - finish(); - }}) - .setNegativeButton(R.string.website_settings_clear_all_dialog_cancel_button, null) - .setIcon(android.R.drawable.ic_dialog_alert) - .show(); - return true; + public void onClick(View v) { + switch (v.getId()) { + case R.id.clear_all_button: + // Show the prompt to clear all origins of their data and geolocation permissions. + new AlertDialog.Builder(getActivity()) + .setTitle(R.string.website_settings_clear_all_dialog_title) + .setMessage(R.string.website_settings_clear_all_dialog_message) + .setPositiveButton(R.string.website_settings_clear_all_dialog_ok_button, + new AlertDialog.OnClickListener() { + public void onClick(DialogInterface dlg, int which) { + WebStorage.getInstance().deleteAllData(); + GeolocationPermissions.getInstance().clearAll(); + WebStorageSizeManager.resetLastOutOfSpaceNotificationTime(); + mAdapter.askForOrigins(); + finish(); + }}) + .setNegativeButton(R.string.website_settings_clear_all_dialog_cancel_button, null) + .setIcon(android.R.drawable.ic_dialog_alert) + .show(); + break; } - return false; } } diff --git a/src/com/android/browser/widget/BookmarkListWidgetProvider.java b/src/com/android/browser/widget/BookmarkListWidgetProvider.java index 04f7b07..2196ae0 100644 --- a/src/com/android/browser/widget/BookmarkListWidgetProvider.java +++ b/src/com/android/browser/widget/BookmarkListWidgetProvider.java @@ -26,7 +26,6 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.net.Uri; -import android.util.Log; import android.widget.RemoteViews; /** diff --git a/src/com/android/browser/widget/BookmarkListWidgetService.java b/src/com/android/browser/widget/BookmarkListWidgetService.java index 14b52b7..8fbe807 100644 --- a/src/com/android/browser/widget/BookmarkListWidgetService.java +++ b/src/com/android/browser/widget/BookmarkListWidgetService.java @@ -24,6 +24,7 @@ import android.content.ContentUris; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.database.ContentObserver; import android.database.Cursor; import android.graphics.Bitmap; @@ -31,9 +32,8 @@ import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; import android.graphics.BitmapFactory.Options; import android.net.Uri; -import android.os.Binder; +import android.os.AsyncTask; import android.os.Handler; -import android.os.HandlerThread; import android.preference.PreferenceManager; import android.provider.BrowserContract; import android.provider.BrowserContract.Bookmarks; @@ -101,7 +101,6 @@ public class BookmarkListWidgetService extends RemoteViewsService { BookmarkFactory fac = mFactories.get(widgetId); if (fac != null && folderId >= 0) { fac.changeFolder(folderId); - AppWidgetManager.getInstance(this).notifyAppWidgetViewDataChanged(widgetId, R.id.bookmarks_list); } } return START_STICKY; @@ -123,10 +122,11 @@ public class BookmarkListWidgetService extends RemoteViewsService { super.onChange(selfChange); // Update all the bookmark widgets - sendBroadcast(new Intent( - BookmarkListWidgetProvider.ACTION_BOOKMARK_APPWIDGET_UPDATE, - null, BookmarkListWidgetService.this, - BookmarkListWidgetProvider.class)); + if (mFactories != null) { + for (BookmarkFactory fac : mFactories.values()) { + fac.loadData(); + } + } } } @@ -137,7 +137,10 @@ public class BookmarkListWidgetService extends RemoteViewsService { Log.w(TAG, "Missing EXTRA_APPWIDGET_ID!"); return null; } else { - BookmarkFactory fac = new BookmarkFactory(this, widgetId); + BookmarkFactory fac = mFactories.get(widgetId); + if (fac == null) { + fac = new BookmarkFactory(getApplicationContext(), widgetId); + } mFactories.put(widgetId, fac); return fac; } @@ -152,13 +155,15 @@ public class BookmarkListWidgetService extends RemoteViewsService { } } - static class BookmarkFactory implements RemoteViewsService.RemoteViewsFactory { + static class BookmarkFactory implements RemoteViewsService.RemoteViewsFactory, + OnSharedPreferenceChangeListener { private List<RenderResult> mBookmarks; private Context mContext; private int mWidgetId; private String mAccountType; private String mAccountName; private Stack<Breadcrumb> mBreadcrumbs; + private LoadBookmarksTask mLoadTask; public BookmarkFactory(Context context, int widgetId) { mBreadcrumbs = new Stack<Breadcrumb>(); @@ -171,12 +176,14 @@ public class BookmarkListWidgetService extends RemoteViewsService { if (!mBreadcrumbs.empty() && mBreadcrumbs.peek().mId == folderId) { mBreadcrumbs.pop(); + loadData(); return; } for (RenderResult res : mBookmarks) { if (res.mId == folderId) { mBreadcrumbs.push(new Breadcrumb(res.mId, res.mTitle)); + loadData(); break; } } @@ -264,30 +271,55 @@ public class BookmarkListWidgetService extends RemoteViewsService { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext); mAccountType = prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_TYPE, null); mAccountName = prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_NAME, null); + prefs.registerOnSharedPreferenceChangeListener(this); loadData(); } @Override public void onDestroy() { recycleBitmaps(); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext); + prefs.unregisterOnSharedPreferenceChangeListener(this); } @Override public void onDataSetChanged() { - loadData(); } void loadData() { - // Reset identity since this could be an IPC call - long token = Binder.clearCallingIdentity(); - update(); - Binder.restoreCallingIdentity(token); + if (mLoadTask != null) { + mLoadTask.cancel(false); + } + mLoadTask = new LoadBookmarksTask(); + mLoadTask.execute(); } - void update() { - recycleBitmaps(); + class LoadBookmarksTask extends AsyncTask<Void, Void, List<RenderResult>> { + private Breadcrumb mFolder; + + @Override + protected void onPreExecute() { + mFolder = mBreadcrumbs.empty() ? null : mBreadcrumbs.peek(); + } + + @Override + protected List<RenderResult> doInBackground(Void... params) { + return loadBookmarks(mFolder); + } + + @Override + protected void onPostExecute(List<RenderResult> result) { + if (!isCancelled() && result != null) { + recycleBitmaps(); + mBookmarks = result; + AppWidgetManager.getInstance(mContext) + .notifyAppWidgetViewDataChanged(mWidgetId, R.id.bookmarks_list); + } + } + } + + List<RenderResult> loadBookmarks(Breadcrumb folder) { String where = null; - Breadcrumb folder = mBreadcrumbs.empty() ? null : mBreadcrumbs.peek(); Uri uri; if (USE_FOLDERS) { uri = BrowserContract.Bookmarks.CONTENT_URI_DEFAULT_FOLDER; @@ -301,18 +333,21 @@ public class BookmarkListWidgetService extends RemoteViewsService { if (!TextUtils.isEmpty(mAccountType) && !TextUtils.isEmpty(mAccountName)) { uri = uri.buildUpon() .appendQueryParameter(Bookmarks.PARAM_ACCOUNT_TYPE, mAccountType) - .appendQueryParameter(Bookmarks.PARAM_ACCOUNT_NAME, mAccountName).build(); + .appendQueryParameter(Bookmarks.PARAM_ACCOUNT_NAME, mAccountName) + .build(); } Cursor c = null; try { c = mContext.getContentResolver().query(uri, PROJECTION, where, null, null); if (c != null) { - mBookmarks = new ArrayList<RenderResult>(c.getCount() + 1); + ArrayList<RenderResult> bookmarks + = new ArrayList<RenderResult>(c.getCount() + 1); if (folder != null) { - RenderResult res = new RenderResult(folder.mId, folder.mTitle, null); + RenderResult res = new RenderResult( + folder.mId, folder.mTitle, null); res.mIsFolder = true; - mBookmarks.add(res); + bookmarks.add(res); } while (c.moveToNext()) { long id = c.getLong(0); @@ -328,8 +363,9 @@ public class BookmarkListWidgetService extends RemoteViewsService { blob, 0, blob.length, options); } res.mIsFolder = c.getInt(4) != 0; - mBookmarks.add(res); + bookmarks.add(res); } + return bookmarks; } } catch (IllegalStateException e) { Log.e(TAG, "update bookmark widget", e); @@ -338,6 +374,7 @@ public class BookmarkListWidgetService extends RemoteViewsService { c.close(); } } + return null; } private void recycleBitmaps() { @@ -351,6 +388,21 @@ public class BookmarkListWidgetService extends RemoteViewsService { } } } + + @Override + public void onSharedPreferenceChanged( + SharedPreferences prefs, String key) { + if (BrowserBookmarksPage.PREF_ACCOUNT_TYPE.equals(key)) { + mAccountType = prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_TYPE, null); + mBreadcrumbs.clear(); + loadData(); + } + if (BrowserBookmarksPage.PREF_ACCOUNT_NAME.equals(key)) { + mAccountName = prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_NAME, null); + mBreadcrumbs.clear(); + loadData(); + } + } } // Class containing the rendering information for a specific bookmark. |