BrowserHistoryPage.java revision 177746d05e1ceefe8421a4fdab7407e1d17b46d6
10c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project/* 20c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 30c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * 40c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 50c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * you may not use this file except in compliance with the License. 60c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * You may obtain a copy of the License at 70c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * 80c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 90c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * 100c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 110c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 120c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * See the License for the specific language governing permissions and 140c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * limitations under the License. 150c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project */ 160c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 170c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectpackage com.android.browser; 180c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 190c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.app.Activity; 2047f7d8d0b36b54a5934daaa6975e05c87e761383Steve Blockimport android.app.AlertDialog; 2147f7d8d0b36b54a5934daaa6975e05c87e761383Steve Blockimport android.app.Dialog; 2264144e49208df145c8362dfa037335c7b9210167Jeff Hamiltonimport android.app.Fragment; 230ce8a942a895cfe1d432076a95f3ed3798ccb002John Reckimport android.app.FragmentBreadCrumbs; 248ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamiltonimport android.app.LoaderManager.LoaderCallbacks; 2580f32627140aefe828ad539f66fc439d1580bae7Dianne Hackbornimport android.content.ClipboardManager; 263f83159b1cd8c732337d966be575233f0d1cae90John Reckimport android.content.ContentResolver; 276fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scrogginsimport android.content.Context; 288ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamiltonimport android.content.CursorLoader; 2947f7d8d0b36b54a5934daaa6975e05c87e761383Steve Blockimport android.content.DialogInterface; 300c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.content.Intent; 318ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamiltonimport android.content.Loader; 324b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reckimport android.content.SharedPreferences; 330c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.content.pm.PackageManager; 340c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.content.pm.ResolveInfo; 350c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.database.Cursor; 360ce8a942a895cfe1d432076a95f3ed3798ccb002John Reckimport android.database.DataSetObserver; 370c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.graphics.Bitmap; 388f0076b720c9ee1e9ef9d29910c261634fd5fb25Patrick Scottimport android.graphics.BitmapFactory; 390ce8a942a895cfe1d432076a95f3ed3798ccb002John Reckimport android.graphics.drawable.Drawable; 409fed39185e23c71afced2f4176d0d859630dbdc5John Reckimport android.net.Uri; 415eb850d10e4d5109f3a65cabc2b17675f2828e04John Reckimport android.os.AsyncTask; 420c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.os.Bundle; 434b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reckimport android.preference.PreferenceManager; 440c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.provider.Browser; 459fed39185e23c71afced2f4176d0d859630dbdc5John Reckimport android.provider.BrowserContract; 464b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reckimport android.provider.BrowserContract.Combined; 470c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.view.ContextMenu; 488ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamiltonimport android.view.ContextMenu.ContextMenuInfo; 4964144e49208df145c8362dfa037335c7b9210167Jeff Hamiltonimport android.view.LayoutInflater; 500c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.view.Menu; 510c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.view.MenuInflater; 520c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.view.MenuItem; 530c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.view.View; 540c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.view.ViewGroup; 550ce8a942a895cfe1d432076a95f3ed3798ccb002John Reckimport android.view.ViewStub; 560c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.webkit.WebIconDatabase.IconListener; 570ce8a942a895cfe1d432076a95f3ed3798ccb002John Reckimport android.widget.AdapterView; 5870413a7cc17c2c779b4b673584946ad590f7eb87John Reckimport android.widget.AdapterView.AdapterContextMenuInfo; 590ce8a942a895cfe1d432076a95f3ed3798ccb002John Reckimport android.widget.AdapterView.OnItemClickListener; 600ce8a942a895cfe1d432076a95f3ed3798ccb002John Reckimport android.widget.BaseAdapter; 610ce8a942a895cfe1d432076a95f3ed3798ccb002John Reckimport android.widget.ListView; 629fed39185e23c71afced2f4176d0d859630dbdc5John Reckimport android.widget.TextView; 63feb941d4be5daaf439f6b463f423618caee15892Leon Scrogginsimport android.widget.Toast; 640c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 650c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project/** 660c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * Activity for displaying the browser's history, divided into 670c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * days of viewing. 680c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project */ 6964144e49208df145c8362dfa037335c7b9210167Jeff Hamiltonpublic class BrowserHistoryPage extends Fragment 7070413a7cc17c2c779b4b673584946ad590f7eb87John Reck implements LoaderCallbacks<Cursor> { 718ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton 728ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton static final int LOADER_HISTORY = 1; 739fed39185e23c71afced2f4176d0d859630dbdc5John Reck static final int LOADER_MOST_VISITED = 2; 740c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 7564144e49208df145c8362dfa037335c7b9210167Jeff Hamilton BookmarksHistoryCallbacks mCallbacks; 768ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton HistoryAdapter mAdapter; 770ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck HistoryChildWrapper mChildWrapper; 788ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton boolean mDisableNewWindow; 798ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton HistoryItem mContextHeader; 809fed39185e23c71afced2f4176d0d859630dbdc5John Reck String mMostVisitsLimit; 810ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck ListView mGroupList, mChildList; 820ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck private ViewGroup mPrefsContainer; 830ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck private FragmentBreadCrumbs mFragmentBreadCrumbs; 840c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 850c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project // Implementation of WebIconDatabase.IconListener 868ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton class IconReceiver implements IconListener { 878ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton @Override 880c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project public void onReceivedIcon(String url, Bitmap icon) { 898ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton mAdapter.notifyDataSetChanged(); 900c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 910c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 928ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton 930c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project // Instance of IconReceiver 948ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton final IconReceiver mIconReceiver = new IconReceiver(); 950ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck private View mRoot; 968ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton 978ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton static interface HistoryQuery { 988ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton static final String[] PROJECTION = new String[] { 994b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reck Combined._ID, // 0 1004b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reck Combined.DATE_LAST_VISITED, // 1 1014b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reck Combined.TITLE, // 2 1024b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reck Combined.URL, // 3 1034b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reck Combined.FAVICON, // 4 1044b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reck Combined.VISITS, // 5 1054b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reck Combined.IS_BOOKMARK, // 6 1068ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton }; 1078ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton 1088ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton static final int INDEX_ID = 0; 1098ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton static final int INDEX_DATE_LAST_VISITED = 1; 1108ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton static final int INDEX_TITE = 2; 1118ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton static final int INDEX_URL = 3; 1128ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton static final int INDEX_FAVICON = 4; 1139fed39185e23c71afced2f4176d0d859630dbdc5John Reck static final int INDEX_VISITS = 5; 1144b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reck static final int INDEX_IS_BOOKMARK = 6; 1158ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton } 1160c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 1170c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project private void copy(CharSequence text) { 11864144e49208df145c8362dfa037335c7b9210167Jeff Hamilton ClipboardManager cm = (ClipboardManager) getActivity().getSystemService( 11964144e49208df145c8362dfa037335c7b9210167Jeff Hamilton Context.CLIPBOARD_SERVICE); 12080f32627140aefe828ad539f66fc439d1580bae7Dianne Hackborn cm.setText(text); 1210c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 1220c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 123e421c2472744ca7d35906f86204790ee97b91ca2Michael Kolb static BrowserHistoryPage newInstance(BookmarksHistoryCallbacks cb, Bundle args) { 124e421c2472744ca7d35906f86204790ee97b91ca2Michael Kolb BrowserHistoryPage bhp = new BrowserHistoryPage(); 125e421c2472744ca7d35906f86204790ee97b91ca2Michael Kolb bhp.mCallbacks = cb; 126e421c2472744ca7d35906f86204790ee97b91ca2Michael Kolb bhp.setArguments(args); 127e421c2472744ca7d35906f86204790ee97b91ca2Michael Kolb return bhp; 128e421c2472744ca7d35906f86204790ee97b91ca2Michael Kolb } 129e421c2472744ca7d35906f86204790ee97b91ca2Michael Kolb 1308ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton @Override 1318ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton public Loader<Cursor> onCreateLoader(int id, Bundle args) { 1324b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reck SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences( 1334b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reck getActivity()); 1344b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reck String accountType = prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_TYPE, null); 1354b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reck String accountName = prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_NAME, null); 1364b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reck Uri.Builder combinedBuilder = Combined.CONTENT_URI.buildUpon(); 1376c22ce6345908c258b9e5043a166229b15653b03John Reck combinedBuilder.appendQueryParameter(BrowserContract.Bookmarks.PARAM_ACCOUNT_TYPE, accountType); 1386c22ce6345908c258b9e5043a166229b15653b03John Reck combinedBuilder.appendQueryParameter(BrowserContract.Bookmarks.PARAM_ACCOUNT_NAME, accountName); 1394b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reck 1408ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton switch (id) { 1418ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton case LOADER_HISTORY: { 1424b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reck String sort = Combined.DATE_LAST_VISITED + " DESC"; 1434b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reck String where = Combined.VISITS + " > 0"; 1444b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reck CursorLoader loader = new CursorLoader(getActivity(), combinedBuilder.build(), 1454b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reck HistoryQuery.PROJECTION, where, null, sort); 1468ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton return loader; 1478ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton } 1488ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton 1499fed39185e23c71afced2f4176d0d859630dbdc5John Reck case LOADER_MOST_VISITED: { 1504b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reck Uri uri = combinedBuilder 1519fed39185e23c71afced2f4176d0d859630dbdc5John Reck .appendQueryParameter(BrowserContract.PARAM_LIMIT, mMostVisitsLimit) 1529fed39185e23c71afced2f4176d0d859630dbdc5John Reck .build(); 1534b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reck String where = Combined.VISITS + " > 0"; 1549fed39185e23c71afced2f4176d0d859630dbdc5John Reck CursorLoader loader = new CursorLoader(getActivity(), uri, 1554b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reck HistoryQuery.PROJECTION, where, null, Combined.VISITS + " DESC"); 1569fed39185e23c71afced2f4176d0d859630dbdc5John Reck return loader; 1579fed39185e23c71afced2f4176d0d859630dbdc5John Reck } 1589fed39185e23c71afced2f4176d0d859630dbdc5John Reck 1598ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton default: { 1608ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton throw new IllegalArgumentException(); 1613a04dd3fa9c62d940256057ac36bf5f1f9281eb3Leon Scroggins III } 1623a04dd3fa9c62d940256057ac36bf5f1f9281eb3Leon Scroggins III } 1638ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton } 1643a04dd3fa9c62d940256057ac36bf5f1f9281eb3Leon Scroggins III 1650ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck void selectGroup(int position) { 1660ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mGroupItemClickListener.onItemClick(null, 1670ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mAdapter.getGroupView(position, false, null, null), 1680ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck position, position); 1690ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 1700ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 1710ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck void checkIfEmpty() { 1720ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck if (mAdapter.mMostVisited != null && mAdapter.mHistoryCursor != null) { 1730ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck // Both cursors have loaded - check to see if we have data 1740ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck if (mAdapter.isEmpty()) { 1750ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mRoot.findViewById(R.id.history).setVisibility(View.GONE); 1760ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mRoot.findViewById(android.R.id.empty).setVisibility(View.VISIBLE); 1770ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } else { 1780ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mRoot.findViewById(R.id.history).setVisibility(View.VISIBLE); 1790ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mRoot.findViewById(android.R.id.empty).setVisibility(View.GONE); 1800ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 1810ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 1820ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 1830ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 1840c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project @Override 1858ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 1868ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton switch (loader.getId()) { 1878ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton case LOADER_HISTORY: { 1888ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton mAdapter.changeCursor(data); 1890ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck if (mAdapter.getGroupCount() > 0) { 1900ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck selectGroup(0); 1910ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 1928ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton 1930ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck checkIfEmpty(); 1949fed39185e23c71afced2f4176d0d859630dbdc5John Reck break; 1959fed39185e23c71afced2f4176d0d859630dbdc5John Reck } 1968ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton 1979fed39185e23c71afced2f4176d0d859630dbdc5John Reck case LOADER_MOST_VISITED: { 1980ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck int preCount = mAdapter.getGroupCount(); 1999fed39185e23c71afced2f4176d0d859630dbdc5John Reck mAdapter.changeMostVisitedCursor(data); 2000ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck if (mAdapter.mHistoryCursor != null 2010ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck && preCount == 0 2020ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck && mAdapter.getGroupCount() > 0) { 2030ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck selectGroup(0); 2040ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 2059fed39185e23c71afced2f4176d0d859630dbdc5John Reck 2060ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck checkIfEmpty(); 2078ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton break; 2088ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton } 2098ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton 2108ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton default: { 2118ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton throw new IllegalArgumentException(); 2128ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton } 2138ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton } 2148ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton } 21564144e49208df145c8362dfa037335c7b9210167Jeff Hamilton 2160ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck @Override 21739772c83f8e210eed1186b66f5f4841aa41776eeDianne Hackborn public void onLoaderReset(Loader<Cursor> loader) { 21839772c83f8e210eed1186b66f5f4841aa41776eeDianne Hackborn } 21939772c83f8e210eed1186b66f5f4841aa41776eeDianne Hackborn 2208ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton @Override 22164144e49208df145c8362dfa037335c7b9210167Jeff Hamilton public void onCreate(Bundle icicle) { 2220c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project super.onCreate(icicle); 2230c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 22464144e49208df145c8362dfa037335c7b9210167Jeff Hamilton setHasOptionsMenu(true); 2258ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton 22664144e49208df145c8362dfa037335c7b9210167Jeff Hamilton Bundle args = getArguments(); 227bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins mDisableNewWindow = args.getBoolean(BrowserBookmarksPage.EXTRA_DISABLE_WINDOW, false); 2289fed39185e23c71afced2f4176d0d859630dbdc5John Reck int mvlimit = getResources().getInteger(R.integer.most_visits_limit); 2299fed39185e23c71afced2f4176d0d859630dbdc5John Reck mMostVisitsLimit = Integer.toString(mvlimit); 23064144e49208df145c8362dfa037335c7b9210167Jeff Hamilton } 231c1cf63a4c15ad81f4d19e10574e9dba91f0b83e4Patrick Scott 23264144e49208df145c8362dfa037335c7b9210167Jeff Hamilton @Override 23364144e49208df145c8362dfa037335c7b9210167Jeff Hamilton public View onCreateView(LayoutInflater inflater, ViewGroup container, 23464144e49208df145c8362dfa037335c7b9210167Jeff Hamilton Bundle savedInstanceState) { 2350ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mRoot = inflater.inflate(R.layout.history, container, false); 2360ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck ViewStub stub = (ViewStub) mRoot.findViewById(R.id.pref_stub); 2370ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck stub.setLayoutResource(com.android.internal.R.layout.preference_list_content); 2380ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck stub.inflate(); 2390ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mGroupList = (ListView) mRoot.findViewById(android.R.id.list); 2400ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mPrefsContainer = (ViewGroup) mRoot.findViewById(com.android.internal.R.id.prefs_frame); 2410ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mFragmentBreadCrumbs = (FragmentBreadCrumbs) mRoot.findViewById(android.R.id.title); 2420ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mFragmentBreadCrumbs.setMaxVisible(1); 2430ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mFragmentBreadCrumbs.setActivity(getActivity()); 2440ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mPrefsContainer.setVisibility(View.VISIBLE); 24564144e49208df145c8362dfa037335c7b9210167Jeff Hamilton mAdapter = new HistoryAdapter(getActivity()); 2460ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mGroupList.setAdapter(new HistoryGroupWrapper(mAdapter)); 2470ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mGroupList.setOnItemClickListener(mGroupItemClickListener); 2480ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mChildWrapper = new HistoryChildWrapper(mAdapter); 2490ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mChildList = new ListView(getActivity()); 2500ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mChildList.setAdapter(mChildWrapper); 25170413a7cc17c2c779b4b673584946ad590f7eb87John Reck mChildList.setOnItemClickListener(mChildItemClickListener); 25270413a7cc17c2c779b4b673584946ad590f7eb87John Reck registerForContextMenu(mChildList); 2530ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck ViewGroup prefs = (ViewGroup) mRoot.findViewById(com.android.internal.R.id.prefs); 2540ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck prefs.addView(mChildList); 2550ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 2560ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck // Start the loaders 257439c9a58765aa6aab95d55422ee61ea8360e912dJohn Reck getLoaderManager().restartLoader(LOADER_HISTORY, null, this); 258439c9a58765aa6aab95d55422ee61ea8360e912dJohn Reck getLoaderManager().restartLoader(LOADER_MOST_VISITED, null, this); 25964144e49208df145c8362dfa037335c7b9210167Jeff Hamilton 26064144e49208df145c8362dfa037335c7b9210167Jeff Hamilton // Register to receive icons in case they haven't all been loaded. 261e421c2472744ca7d35906f86204790ee97b91ca2Michael Kolb CombinedBookmarkHistoryView.getIconListenerSet().addListener(mIconReceiver); 2620ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck return mRoot; 2630c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 2640c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 2650ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck private OnItemClickListener mGroupItemClickListener = new OnItemClickListener() { 2660ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck @Override 2670ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck public void onItemClick( 2680ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck AdapterView<?> parent, View view, int position, long id) { 2690ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck CharSequence title = ((TextView) view).getText(); 2700ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mFragmentBreadCrumbs.setTitle(title, title); 2710ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mChildWrapper.setSelectedGroup(position); 2720ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 2730ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck }; 2740ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 27570413a7cc17c2c779b4b673584946ad590f7eb87John Reck private OnItemClickListener mChildItemClickListener = new OnItemClickListener() { 27670413a7cc17c2c779b4b673584946ad590f7eb87John Reck @Override 27770413a7cc17c2c779b4b673584946ad590f7eb87John Reck public void onItemClick( 27870413a7cc17c2c779b4b673584946ad590f7eb87John Reck AdapterView<?> parent, View view, int position, long id) { 27970413a7cc17c2c779b4b673584946ad590f7eb87John Reck mCallbacks.onUrlSelected(((HistoryItem) view).getUrl(), false); 28070413a7cc17c2c779b4b673584946ad590f7eb87John Reck } 28170413a7cc17c2c779b4b673584946ad590f7eb87John Reck }; 28270413a7cc17c2c779b4b673584946ad590f7eb87John Reck 2830c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project @Override 28464144e49208df145c8362dfa037335c7b9210167Jeff Hamilton public void onDestroy() { 285b8a9cb0e2b3b2a1bb250853a79b8ea2046ff3d6eGrace Kloba super.onDestroy(); 286e421c2472744ca7d35906f86204790ee97b91ca2Michael Kolb CombinedBookmarkHistoryView.getIconListenerSet().removeListener(mIconReceiver); 28771e76c71d8fb70433a60521dfdbcd4e7a8762ef8Dianne Hackborn getLoaderManager().destroyLoader(LOADER_HISTORY); 28871e76c71d8fb70433a60521dfdbcd4e7a8762ef8Dianne Hackborn getLoaderManager().destroyLoader(LOADER_MOST_VISITED); 289b8a9cb0e2b3b2a1bb250853a79b8ea2046ff3d6eGrace Kloba } 290b8a9cb0e2b3b2a1bb250853a79b8ea2046ff3d6eGrace Kloba 291b8a9cb0e2b3b2a1bb250853a79b8ea2046ff3d6eGrace Kloba @Override 29264144e49208df145c8362dfa037335c7b9210167Jeff Hamilton public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 2930c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project inflater.inflate(R.menu.history, menu); 2940c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 2950c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 2960c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project @Override 2970c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project public boolean onOptionsItemSelected(MenuItem item) { 2980c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project switch (item.getItemId()) { 2990c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project case R.id.clear_history_menu_id: 3003f83159b1cd8c732337d966be575233f0d1cae90John Reck final ContentResolver resolver = getActivity().getContentResolver(); 3015eb850d10e4d5109f3a65cabc2b17675f2828e04John Reck final ClearHistoryTask clear = new ClearHistoryTask(resolver, mCallbacks); 30247f7d8d0b36b54a5934daaa6975e05c87e761383Steve Block AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()) 30347f7d8d0b36b54a5934daaa6975e05c87e761383Steve Block .setTitle(R.string.clear) 30447f7d8d0b36b54a5934daaa6975e05c87e761383Steve Block .setMessage(R.string.pref_privacy_clear_history_dlg) 30547f7d8d0b36b54a5934daaa6975e05c87e761383Steve Block .setIcon(android.R.drawable.ic_dialog_alert) 30647f7d8d0b36b54a5934daaa6975e05c87e761383Steve Block .setNegativeButton(R.string.cancel, null) 30747f7d8d0b36b54a5934daaa6975e05c87e761383Steve Block .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { 30847f7d8d0b36b54a5934daaa6975e05c87e761383Steve Block @Override 30947f7d8d0b36b54a5934daaa6975e05c87e761383Steve Block public void onClick(DialogInterface dialog, int which) { 31047f7d8d0b36b54a5934daaa6975e05c87e761383Steve Block if (which == DialogInterface.BUTTON_POSITIVE) { 3115eb850d10e4d5109f3a65cabc2b17675f2828e04John Reck clear.execute(); 31247f7d8d0b36b54a5934daaa6975e05c87e761383Steve Block } 31347f7d8d0b36b54a5934daaa6975e05c87e761383Steve Block } 31447f7d8d0b36b54a5934daaa6975e05c87e761383Steve Block }); 31547f7d8d0b36b54a5934daaa6975e05c87e761383Steve Block final Dialog dialog = builder.create(); 31647f7d8d0b36b54a5934daaa6975e05c87e761383Steve Block dialog.show(); 3170c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project return true; 318e421c2472744ca7d35906f86204790ee97b91ca2Michael Kolb 3190c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project default: 3200c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project break; 321e421c2472744ca7d35906f86204790ee97b91ca2Michael Kolb } 3220c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project return super.onOptionsItemSelected(item); 3230c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 324186e593776c396bde3d720addd6f6842fe880a7cLeon Scroggins 3255eb850d10e4d5109f3a65cabc2b17675f2828e04John Reck static class ClearHistoryTask extends AsyncTask<Void, Void, Void> { 3265eb850d10e4d5109f3a65cabc2b17675f2828e04John Reck ContentResolver mResolver; 3275eb850d10e4d5109f3a65cabc2b17675f2828e04John Reck BookmarksHistoryCallbacks mCallbacks; 3285eb850d10e4d5109f3a65cabc2b17675f2828e04John Reck 3295eb850d10e4d5109f3a65cabc2b17675f2828e04John Reck public ClearHistoryTask(ContentResolver resolver, 3305eb850d10e4d5109f3a65cabc2b17675f2828e04John Reck BookmarksHistoryCallbacks callbacks) { 3315eb850d10e4d5109f3a65cabc2b17675f2828e04John Reck mResolver = resolver; 3325eb850d10e4d5109f3a65cabc2b17675f2828e04John Reck mCallbacks = callbacks; 3335eb850d10e4d5109f3a65cabc2b17675f2828e04John Reck } 3345eb850d10e4d5109f3a65cabc2b17675f2828e04John Reck @Override 3355eb850d10e4d5109f3a65cabc2b17675f2828e04John Reck protected Void doInBackground(Void... params) { 3365eb850d10e4d5109f3a65cabc2b17675f2828e04John Reck Browser.clearHistory(mResolver); 3375eb850d10e4d5109f3a65cabc2b17675f2828e04John Reck return null; 3385eb850d10e4d5109f3a65cabc2b17675f2828e04John Reck } 3395eb850d10e4d5109f3a65cabc2b17675f2828e04John Reck 3405eb850d10e4d5109f3a65cabc2b17675f2828e04John Reck @Override 3415eb850d10e4d5109f3a65cabc2b17675f2828e04John Reck protected void onPostExecute(Void result) { 3425eb850d10e4d5109f3a65cabc2b17675f2828e04John Reck mCallbacks.onRemoveParentChildRelationships(); 3435eb850d10e4d5109f3a65cabc2b17675f2828e04John Reck } 3445eb850d10e4d5109f3a65cabc2b17675f2828e04John Reck } 3455eb850d10e4d5109f3a65cabc2b17675f2828e04John Reck 3460c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project @Override 34764144e49208df145c8362dfa037335c7b9210167Jeff Hamilton public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { 34870413a7cc17c2c779b4b673584946ad590f7eb87John Reck AdapterContextMenuInfo i = (AdapterContextMenuInfo) menuInfo; 3490c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 3500c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project // Inflate the menu 35164144e49208df145c8362dfa037335c7b9210167Jeff Hamilton Activity parent = getActivity(); 35264144e49208df145c8362dfa037335c7b9210167Jeff Hamilton MenuInflater inflater = parent.getMenuInflater(); 3530c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project inflater.inflate(R.menu.historycontext, menu); 3540c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 355186e593776c396bde3d720addd6f6842fe880a7cLeon Scroggins HistoryItem historyItem = (HistoryItem) i.targetView; 356186e593776c396bde3d720addd6f6842fe880a7cLeon Scroggins 3570c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project // Setup the header 358186e593776c396bde3d720addd6f6842fe880a7cLeon Scroggins if (mContextHeader == null) { 359177746d05e1ceefe8421a4fdab7407e1d17b46d6John Reck mContextHeader = new HistoryItem(parent, false); 360186e593776c396bde3d720addd6f6842fe880a7cLeon Scroggins } else if (mContextHeader.getParent() != null) { 361186e593776c396bde3d720addd6f6842fe880a7cLeon Scroggins ((ViewGroup) mContextHeader.getParent()).removeView(mContextHeader); 362186e593776c396bde3d720addd6f6842fe880a7cLeon Scroggins } 363186e593776c396bde3d720addd6f6842fe880a7cLeon Scroggins historyItem.copyTo(mContextHeader); 364186e593776c396bde3d720addd6f6842fe880a7cLeon Scroggins menu.setHeaderView(mContextHeader); 3650c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 366190095d42ef36347df265f40df190ec8be190d9eLeon Scroggins // Only show open in new tab if it was not explicitly disabled 367190095d42ef36347df265f40df190ec8be190d9eLeon Scroggins if (mDisableNewWindow) { 368190095d42ef36347df265f40df190ec8be190d9eLeon Scroggins menu.findItem(R.id.new_window_context_menu_id).setVisible(false); 369190095d42ef36347df265f40df190ec8be190d9eLeon Scroggins } 370186e593776c396bde3d720addd6f6842fe880a7cLeon Scroggins // For a bookmark, provide the option to remove it from bookmarks 371186e593776c396bde3d720addd6f6842fe880a7cLeon Scroggins if (historyItem.isBookmark()) { 372186e593776c396bde3d720addd6f6842fe880a7cLeon Scroggins MenuItem item = menu.findItem(R.id.save_to_bookmarks_menu_id); 373186e593776c396bde3d720addd6f6842fe880a7cLeon Scroggins item.setTitle(R.string.remove_from_bookmarks); 374186e593776c396bde3d720addd6f6842fe880a7cLeon Scroggins } 3750c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project // decide whether to show the share link option 37664144e49208df145c8362dfa037335c7b9210167Jeff Hamilton PackageManager pm = parent.getPackageManager(); 3770c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project Intent send = new Intent(Intent.ACTION_SEND); 3780c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project send.setType("text/plain"); 3790c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project ResolveInfo ri = pm.resolveActivity(send, PackageManager.MATCH_DEFAULT_ONLY); 3800c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project menu.findItem(R.id.share_link_context_menu_id).setVisible(ri != null); 381e421c2472744ca7d35906f86204790ee97b91ca2Michael Kolb 3820c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project super.onCreateContextMenu(menu, v, menuInfo); 3830c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 384e421c2472744ca7d35906f86204790ee97b91ca2Michael Kolb 3850c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project @Override 3860c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project public boolean onContextItemSelected(MenuItem item) { 38770413a7cc17c2c779b4b673584946ad590f7eb87John Reck AdapterContextMenuInfo i = 38870413a7cc17c2c779b4b673584946ad590f7eb87John Reck (AdapterContextMenuInfo) item.getMenuInfo(); 389c8cae086f23bd8f3d740befcdbbda9a8688cc2a3Leon Scroggins if (i == null) { 390c8cae086f23bd8f3d740befcdbbda9a8688cc2a3Leon Scroggins return false; 391c8cae086f23bd8f3d740befcdbbda9a8688cc2a3Leon Scroggins } 392186e593776c396bde3d720addd6f6842fe880a7cLeon Scroggins HistoryItem historyItem = (HistoryItem) i.targetView; 393186e593776c396bde3d720addd6f6842fe880a7cLeon Scroggins String url = historyItem.getUrl(); 394186e593776c396bde3d720addd6f6842fe880a7cLeon Scroggins String title = historyItem.getName(); 39564144e49208df145c8362dfa037335c7b9210167Jeff Hamilton Activity activity = getActivity(); 3960c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project switch (item.getItemId()) { 3970c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project case R.id.open_context_menu_id: 39864144e49208df145c8362dfa037335c7b9210167Jeff Hamilton mCallbacks.onUrlSelected(url, false); 3990c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project return true; 4000c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project case R.id.new_window_context_menu_id: 40164144e49208df145c8362dfa037335c7b9210167Jeff Hamilton mCallbacks.onUrlSelected(url, true); 4020c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project return true; 4030c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project case R.id.save_to_bookmarks_menu_id: 404186e593776c396bde3d720addd6f6842fe880a7cLeon Scroggins if (historyItem.isBookmark()) { 40564144e49208df145c8362dfa037335c7b9210167Jeff Hamilton Bookmarks.removeFromBookmarks(activity, activity.getContentResolver(), 406c95261955cf08f30b484b6a229c4bcff42c645ceAndrei Popescu url, title); 407186e593776c396bde3d720addd6f6842fe880a7cLeon Scroggins } else { 40864144e49208df145c8362dfa037335c7b9210167Jeff Hamilton Browser.saveBookmark(activity, title, url); 409186e593776c396bde3d720addd6f6842fe880a7cLeon Scroggins } 4100c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project return true; 4110c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project case R.id.share_link_context_menu_id: 41264144e49208df145c8362dfa037335c7b9210167Jeff Hamilton Browser.sendString(activity, url, 41364144e49208df145c8362dfa037335c7b9210167Jeff Hamilton activity.getText(R.string.choosertitle_sharevia).toString()); 4140c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project return true; 415a5d669e4c08f0e64387c2c539c41a26ac8c845abLeon Scroggins case R.id.copy_url_context_menu_id: 4160c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project copy(url); 4170c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project return true; 4180c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project case R.id.delete_context_menu_id: 41964144e49208df145c8362dfa037335c7b9210167Jeff Hamilton Browser.deleteFromHistory(activity.getContentResolver(), url); 4200c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project return true; 421feb941d4be5daaf439f6b463f423618caee15892Leon Scroggins case R.id.homepage_context_menu_id: 42264144e49208df145c8362dfa037335c7b9210167Jeff Hamilton BrowserSettings.getInstance().setHomePage(activity, url); 42364144e49208df145c8362dfa037335c7b9210167Jeff Hamilton Toast.makeText(activity, R.string.homepage_set, Toast.LENGTH_LONG).show(); 424feb941d4be5daaf439f6b463f423618caee15892Leon Scroggins return true; 4250c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project default: 4260c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project break; 4270c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 4280c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project return super.onContextItemSelected(item); 4290c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 4308ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton 4310ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck private static abstract class HistoryWrapper extends BaseAdapter { 4320ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 4330ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck protected HistoryAdapter mAdapter; 4340ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck private DataSetObserver mObserver = new DataSetObserver() { 4350ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck @Override 4360ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck public void onChanged() { 4370ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck super.onChanged(); 4380ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck notifyDataSetChanged(); 4390ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 4400ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 4410ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck @Override 4420ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck public void onInvalidated() { 4430ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck super.onInvalidated(); 4440ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck notifyDataSetInvalidated(); 4450ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 4460ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck }; 4470ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 4480ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck public HistoryWrapper(HistoryAdapter adapter) { 4490ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mAdapter = adapter; 4500ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mAdapter.registerDataSetObserver(mObserver); 4510ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 4520ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 4530ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 4540ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck private static class HistoryGroupWrapper extends HistoryWrapper { 4550ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 4560ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck public HistoryGroupWrapper(HistoryAdapter adapter) { 4570ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck super(adapter); 4580ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 4590ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 4600ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck @Override 4610ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck public int getCount() { 4620ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck return mAdapter.getGroupCount(); 4630ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 4640ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 4650ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck @Override 4660ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck public Object getItem(int position) { 4670ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck return null; 4680ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 4690ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 4700ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck @Override 4710ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck public long getItemId(int position) { 4720ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck return position; 4730ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 4740ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 4750ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck @Override 4760ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck public View getView(int position, View convertView, ViewGroup parent) { 4770ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck return mAdapter.getGroupView(position, false, convertView, parent); 4780ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 4790ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 4800ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 4810ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 4820ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck private static class HistoryChildWrapper extends HistoryWrapper { 4830ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 4840ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck private int mSelectedGroup; 4850ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 4860ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck public HistoryChildWrapper(HistoryAdapter adapter) { 4870ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck super(adapter); 4880ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 4890ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 4900ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck void setSelectedGroup(int groupPosition) { 4910ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mSelectedGroup = groupPosition; 4920ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck notifyDataSetChanged(); 4930ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 4940ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 4950ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck @Override 4960ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck public int getCount() { 4970ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck return mAdapter.getChildrenCount(mSelectedGroup); 4980ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 4990ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 5000ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck @Override 5010ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck public Object getItem(int position) { 5020ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck return null; 5030ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 5040ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 5050ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck @Override 5060ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck public long getItemId(int position) { 5070ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck return position; 5080ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 5090ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 5100ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck @Override 5110ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck public View getView(int position, View convertView, ViewGroup parent) { 5120ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck return mAdapter.getChildView(mSelectedGroup, position, 5130ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck false, convertView, parent); 5140ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 5150ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 5160ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 5170ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 5186fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins private class HistoryAdapter extends DateSortedExpandableListAdapter { 5190ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck 5209fed39185e23c71afced2f4176d0d859630dbdc5John Reck private Cursor mMostVisited, mHistoryCursor; 5210ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck Drawable mFaviconBackground; 5229fed39185e23c71afced2f4176d0d859630dbdc5John Reck 5238ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton HistoryAdapter(Context context) { 5248ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton super(context, HistoryQuery.INDEX_DATE_LAST_VISITED); 5250ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck mFaviconBackground = BookmarkUtils.createListFaviconBackground(context); 5260c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 5270c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 5288ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton @Override 5299fed39185e23c71afced2f4176d0d859630dbdc5John Reck public void changeCursor(Cursor cursor) { 5309fed39185e23c71afced2f4176d0d859630dbdc5John Reck mHistoryCursor = cursor; 5319fed39185e23c71afced2f4176d0d859630dbdc5John Reck super.changeCursor(cursor); 5329fed39185e23c71afced2f4176d0d859630dbdc5John Reck } 5339fed39185e23c71afced2f4176d0d859630dbdc5John Reck 5349fed39185e23c71afced2f4176d0d859630dbdc5John Reck void changeMostVisitedCursor(Cursor cursor) { 5359fed39185e23c71afced2f4176d0d859630dbdc5John Reck if (mMostVisited == cursor) { 5369fed39185e23c71afced2f4176d0d859630dbdc5John Reck return; 5379fed39185e23c71afced2f4176d0d859630dbdc5John Reck } 5389fed39185e23c71afced2f4176d0d859630dbdc5John Reck if (mMostVisited != null) { 5399fed39185e23c71afced2f4176d0d859630dbdc5John Reck mMostVisited.unregisterDataSetObserver(mDataSetObserver); 5409fed39185e23c71afced2f4176d0d859630dbdc5John Reck mMostVisited.close(); 5419fed39185e23c71afced2f4176d0d859630dbdc5John Reck } 5429fed39185e23c71afced2f4176d0d859630dbdc5John Reck mMostVisited = cursor; 54306e49cecf9b2d0dbae6adb637a719d1885bf92a2John Reck if (mMostVisited != null) { 54406e49cecf9b2d0dbae6adb637a719d1885bf92a2John Reck mMostVisited.registerDataSetObserver(mDataSetObserver); 54506e49cecf9b2d0dbae6adb637a719d1885bf92a2John Reck } 54606e49cecf9b2d0dbae6adb637a719d1885bf92a2John Reck notifyDataSetChanged(); 5479fed39185e23c71afced2f4176d0d859630dbdc5John Reck } 5489fed39185e23c71afced2f4176d0d859630dbdc5John Reck 5499fed39185e23c71afced2f4176d0d859630dbdc5John Reck @Override 5509fed39185e23c71afced2f4176d0d859630dbdc5John Reck public long getChildId(int groupPosition, int childPosition) { 5519fed39185e23c71afced2f4176d0d859630dbdc5John Reck if (moveCursorToChildPosition(groupPosition, childPosition)) { 5529fed39185e23c71afced2f4176d0d859630dbdc5John Reck Cursor cursor = getCursor(groupPosition); 5539fed39185e23c71afced2f4176d0d859630dbdc5John Reck return cursor.getLong(HistoryQuery.INDEX_ID); 5549fed39185e23c71afced2f4176d0d859630dbdc5John Reck } 5559fed39185e23c71afced2f4176d0d859630dbdc5John Reck return 0; 5569fed39185e23c71afced2f4176d0d859630dbdc5John Reck } 5579fed39185e23c71afced2f4176d0d859630dbdc5John Reck 5589fed39185e23c71afced2f4176d0d859630dbdc5John Reck @Override 5599fed39185e23c71afced2f4176d0d859630dbdc5John Reck public int getGroupCount() { 5609fed39185e23c71afced2f4176d0d859630dbdc5John Reck return super.getGroupCount() + (mMostVisited != null ? 1 : 0); 5619fed39185e23c71afced2f4176d0d859630dbdc5John Reck } 5629fed39185e23c71afced2f4176d0d859630dbdc5John Reck 5639fed39185e23c71afced2f4176d0d859630dbdc5John Reck @Override 5649fed39185e23c71afced2f4176d0d859630dbdc5John Reck public int getChildrenCount(int groupPosition) { 5659fed39185e23c71afced2f4176d0d859630dbdc5John Reck if (groupPosition >= super.getGroupCount()) { 5660ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck if (mMostVisited == null) { 5670ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck return 0; 5680ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck } 5699fed39185e23c71afced2f4176d0d859630dbdc5John Reck return mMostVisited.getCount(); 5709fed39185e23c71afced2f4176d0d859630dbdc5John Reck } 5719fed39185e23c71afced2f4176d0d859630dbdc5John Reck return super.getChildrenCount(groupPosition); 5729fed39185e23c71afced2f4176d0d859630dbdc5John Reck } 5739fed39185e23c71afced2f4176d0d859630dbdc5John Reck 5749fed39185e23c71afced2f4176d0d859630dbdc5John Reck @Override 5759fed39185e23c71afced2f4176d0d859630dbdc5John Reck public boolean isEmpty() { 5769fed39185e23c71afced2f4176d0d859630dbdc5John Reck if (!super.isEmpty()) { 5779fed39185e23c71afced2f4176d0d859630dbdc5John Reck return false; 5789fed39185e23c71afced2f4176d0d859630dbdc5John Reck } 5799fed39185e23c71afced2f4176d0d859630dbdc5John Reck return mMostVisited == null 5809fed39185e23c71afced2f4176d0d859630dbdc5John Reck || mMostVisited.isClosed() 5819fed39185e23c71afced2f4176d0d859630dbdc5John Reck || mMostVisited.getCount() == 0; 5829fed39185e23c71afced2f4176d0d859630dbdc5John Reck } 5839fed39185e23c71afced2f4176d0d859630dbdc5John Reck 5849fed39185e23c71afced2f4176d0d859630dbdc5John Reck Cursor getCursor(int groupPosition) { 5859fed39185e23c71afced2f4176d0d859630dbdc5John Reck if (groupPosition >= super.getGroupCount()) { 5869fed39185e23c71afced2f4176d0d859630dbdc5John Reck return mMostVisited; 5879fed39185e23c71afced2f4176d0d859630dbdc5John Reck } 5889fed39185e23c71afced2f4176d0d859630dbdc5John Reck return mHistoryCursor; 5899fed39185e23c71afced2f4176d0d859630dbdc5John Reck } 5909fed39185e23c71afced2f4176d0d859630dbdc5John Reck 5919fed39185e23c71afced2f4176d0d859630dbdc5John Reck @Override 5929fed39185e23c71afced2f4176d0d859630dbdc5John Reck public View getGroupView(int groupPosition, boolean isExpanded, 5939fed39185e23c71afced2f4176d0d859630dbdc5John Reck View convertView, ViewGroup parent) { 5949fed39185e23c71afced2f4176d0d859630dbdc5John Reck if (groupPosition >= super.getGroupCount()) { 59559280307b381a247a2f6a5299a5893f5f5337306John Reck if (mMostVisited == null || mMostVisited.isClosed()) { 59659280307b381a247a2f6a5299a5893f5f5337306John Reck throw new IllegalStateException("Data is not valid"); 59759280307b381a247a2f6a5299a5893f5f5337306John Reck } 5989fed39185e23c71afced2f4176d0d859630dbdc5John Reck TextView item; 5999fed39185e23c71afced2f4176d0d859630dbdc5John Reck if (null == convertView || !(convertView instanceof TextView)) { 6009fed39185e23c71afced2f4176d0d859630dbdc5John Reck LayoutInflater factory = LayoutInflater.from(getContext()); 6019fed39185e23c71afced2f4176d0d859630dbdc5John Reck item = (TextView) factory.inflate(R.layout.history_header, null); 6029fed39185e23c71afced2f4176d0d859630dbdc5John Reck } else { 6039fed39185e23c71afced2f4176d0d859630dbdc5John Reck item = (TextView) convertView; 6049fed39185e23c71afced2f4176d0d859630dbdc5John Reck } 6059fed39185e23c71afced2f4176d0d859630dbdc5John Reck item.setText(R.string.tab_most_visited); 6069fed39185e23c71afced2f4176d0d859630dbdc5John Reck return item; 6079fed39185e23c71afced2f4176d0d859630dbdc5John Reck } 6089fed39185e23c71afced2f4176d0d859630dbdc5John Reck return super.getGroupView(groupPosition, isExpanded, convertView, parent); 6099fed39185e23c71afced2f4176d0d859630dbdc5John Reck } 6109fed39185e23c71afced2f4176d0d859630dbdc5John Reck 6119fed39185e23c71afced2f4176d0d859630dbdc5John Reck @Override 6129fed39185e23c71afced2f4176d0d859630dbdc5John Reck boolean moveCursorToChildPosition( 6139fed39185e23c71afced2f4176d0d859630dbdc5John Reck int groupPosition, int childPosition) { 6149fed39185e23c71afced2f4176d0d859630dbdc5John Reck if (groupPosition >= super.getGroupCount()) { 61559280307b381a247a2f6a5299a5893f5f5337306John Reck if (mMostVisited != null && !mMostVisited.isClosed()) { 6169fed39185e23c71afced2f4176d0d859630dbdc5John Reck mMostVisited.moveToPosition(childPosition); 6179fed39185e23c71afced2f4176d0d859630dbdc5John Reck return true; 6189fed39185e23c71afced2f4176d0d859630dbdc5John Reck } 6199fed39185e23c71afced2f4176d0d859630dbdc5John Reck return false; 6209fed39185e23c71afced2f4176d0d859630dbdc5John Reck } 6219fed39185e23c71afced2f4176d0d859630dbdc5John Reck return super.moveCursorToChildPosition(groupPosition, childPosition); 6229fed39185e23c71afced2f4176d0d859630dbdc5John Reck } 6239fed39185e23c71afced2f4176d0d859630dbdc5John Reck 6249fed39185e23c71afced2f4176d0d859630dbdc5John Reck @Override 6250c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project public View getChildView(int groupPosition, int childPosition, boolean isLastChild, 6260c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project View convertView, ViewGroup parent) { 627772927a9fa4acaafdef4ae3bde91cf0bb822ebd7Michael Kolb HistoryItem item; 628772927a9fa4acaafdef4ae3bde91cf0bb822ebd7Michael Kolb if (null == convertView || !(convertView instanceof HistoryItem)) { 629772927a9fa4acaafdef4ae3bde91cf0bb822ebd7Michael Kolb item = new HistoryItem(getContext()); 6300c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project // Add padding on the left so it will be indented from the 6310c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project // arrows on the group views. 6320c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project item.setPadding(item.getPaddingLeft() + 10, 6330c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project item.getPaddingTop(), 6340c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project item.getPaddingRight(), 6350c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project item.getPaddingBottom()); 6360ce8a942a895cfe1d432076a95f3ed3798ccb002John Reck item.setFaviconBackground(mFaviconBackground); 6370c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } else { 638772927a9fa4acaafdef4ae3bde91cf0bb822ebd7Michael Kolb item = (HistoryItem) convertView; 6390c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 6408ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton 64122807d1975984667829138d7d47d2020f8632f11Leon Scroggins // Bail early if the Cursor is closed. 6426fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins if (!moveCursorToChildPosition(groupPosition, childPosition)) { 6436fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins return item; 6440c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 6458ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton 6469fed39185e23c71afced2f4176d0d859630dbdc5John Reck Cursor cursor = getCursor(groupPosition); 6479fed39185e23c71afced2f4176d0d859630dbdc5John Reck item.setName(cursor.getString(HistoryQuery.INDEX_TITE)); 6489fed39185e23c71afced2f4176d0d859630dbdc5John Reck String url = cursor.getString(HistoryQuery.INDEX_URL); 6490c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project item.setUrl(url); 6509fed39185e23c71afced2f4176d0d859630dbdc5John Reck byte[] data = cursor.getBlob(HistoryQuery.INDEX_FAVICON); 6518f0076b720c9ee1e9ef9d29910c261634fd5fb25Patrick Scott if (data != null) { 6528f0076b720c9ee1e9ef9d29910c261634fd5fb25Patrick Scott item.setFavicon(BitmapFactory.decodeByteArray(data, 0, 6538f0076b720c9ee1e9ef9d29910c261634fd5fb25Patrick Scott data.length)); 6548f0076b720c9ee1e9ef9d29910c261634fd5fb25Patrick Scott } else { 655e421c2472744ca7d35906f86204790ee97b91ca2Michael Kolb item.setFavicon(CombinedBookmarkHistoryView 6568f0076b720c9ee1e9ef9d29910c261634fd5fb25Patrick Scott .getIconListenerSet().getFavicon(url)); 6578f0076b720c9ee1e9ef9d29910c261634fd5fb25Patrick Scott } 6584b59db8bc6b609307dfcb346283378c5ea993d7cJohn Reck item.setIsBookmark(cursor.getInt(HistoryQuery.INDEX_IS_BOOKMARK) == 1); 6590c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project return item; 6600c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 6610c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 6620c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project} 663