blob: b627994ed87cc7763aa654ecba2340f0d244af1b [file] [log] [blame]
The Android Open Source Project0c908882009-03-03 19:32:16 -08001/*
Dany Rybnikov535d4af2014-06-23 09:16:09 +03002 * Copyright (c) 2014, Linux Foundation. All rights reserved.
The Android Open Source Project0c908882009-03-03 19:32:16 -08003 * Copyright (C) 2006 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
Bijan Amirzada41242f22014-03-21 12:12:18 -070018package com.android.browser;
The Android Open Source Project0c908882009-03-03 19:32:16 -080019
20import android.app.Activity;
Jeff Hamilton64144e42010-08-18 16:31:59 -050021import android.app.Fragment;
Jeff Hamilton84029622010-08-05 14:29:28 -050022import android.app.LoaderManager;
Dianne Hackborneb07b172010-08-26 22:18:14 -070023import android.content.ClipData;
Michael Kolbbef7a752010-08-25 17:11:35 -070024import android.content.ClipboardManager;
Jeff Hamilton84029622010-08-05 14:29:28 -050025import android.content.ContentUris;
Dianne Hackborn80f32622010-08-05 14:17:53 -070026import android.content.Context;
John Reck71efc2b2011-05-09 16:54:28 -070027import android.content.CursorLoader;
The Android Open Source Project0c908882009-03-03 19:32:16 -080028import android.content.Intent;
Jeff Hamilton84029622010-08-05 14:29:28 -050029import android.content.Loader;
John Reck4f61ee42011-08-22 16:31:14 -070030import android.content.SharedPreferences;
John Reckb3417f02011-01-14 11:01:05 -080031import android.content.res.Configuration;
32import android.content.res.Resources;
Jeff Hamilton84029622010-08-05 14:29:28 -050033import android.database.Cursor;
The Android Open Source Project0c908882009-03-03 19:32:16 -080034import android.graphics.Bitmap;
Jeff Hamilton84029622010-08-05 14:29:28 -050035import android.graphics.BitmapFactory;
John Reckf94abcf2011-10-10 15:33:48 -070036import android.graphics.BitmapFactory.Options;
Dave Tharp490ca7f2015-06-16 11:17:34 -070037import android.graphics.Canvas;
Jeff Hamilton84029622010-08-05 14:29:28 -050038import android.net.Uri;
John Reckc8490812010-11-22 14:15:36 -080039import android.os.AsyncTask;
The Android Open Source Project0c908882009-03-03 19:32:16 -080040import android.os.Bundle;
Dave Tharp490ca7f2015-06-16 11:17:34 -070041import android.util.Log;
The Android Open Source Project0c908882009-03-03 19:32:16 -080042import android.view.ContextMenu;
Jeff Hamiltondb90aa82010-09-16 03:38:04 -050043import android.view.ContextMenu.ContextMenuInfo;
Jeff Hamilton64144e42010-08-18 16:31:59 -050044import android.view.LayoutInflater;
The Android Open Source Project0c908882009-03-03 19:32:16 -080045import android.view.MenuInflater;
46import android.view.MenuItem;
47import android.view.View;
Jeff Hamiltondb90aa82010-09-16 03:38:04 -050048import android.view.ViewGroup;
Pankaj Garg49b79252014-11-07 17:33:41 -080049import android.widget.Button;
John Reck71efc2b2011-05-09 16:54:28 -070050import android.widget.ExpandableListView;
51import android.widget.ExpandableListView.OnChildClickListener;
Jeff Hamilton84029622010-08-05 14:29:28 -050052import android.widget.Toast;
The Android Open Source Project0c908882009-03-03 19:32:16 -080053
Dave Tharp9a082b12015-06-19 08:46:57 -070054import com.android.browser.mdm.EditBookmarksRestriction;
Dave Tharp490ca7f2015-06-16 11:17:34 -070055import com.android.browser.mdm.ManagedBookmarksRestriction;
Bijan Amirzada41242f22014-03-21 12:12:18 -070056import com.android.browser.platformsupport.BrowserContract;
57import com.android.browser.platformsupport.BrowserContract.Accounts;
58import com.android.browser.provider.BrowserProvider2;
59import com.android.browser.view.BookmarkExpandableView;
60import com.android.browser.view.BookmarkExpandableView.BookmarkContextMenuInfo;
Bijan Amirzada9b1e9882014-02-26 17:15:46 -080061
62import java.util.HashMap;
John Recke7c97de2011-05-27 14:42:43 -070063
John Reck4f61ee42011-08-22 16:31:14 -070064import org.json.JSONException;
65import org.json.JSONObject;
66
Dany Rybnikovdb490c12015-03-29 15:46:24 +030067import org.codeaurora.net.NetworkServices;
Dany Rybnikov535d4af2014-06-23 09:16:09 +030068
John Reck608baa72010-11-24 10:32:28 -080069interface BookmarksPageCallbacks {
70 // Return true if handled
71 boolean onBookmarkSelected(Cursor c, boolean isFolder);
72 // Return true if handled
John Reckd3e4d5b2011-07-13 15:48:43 -070073 boolean onOpenInNewWindow(String... urls);
John Reck608baa72010-11-24 10:32:28 -080074}
75
The Android Open Source Project0c908882009-03-03 19:32:16 -080076/**
77 * View showing the user's bookmarks in the browser.
78 */
Jeff Hamilton64144e42010-08-18 16:31:59 -050079public class BrowserBookmarksPage extends Fragment implements View.OnCreateContextMenuListener,
John Reck9db95292011-06-20 13:00:12 -070080 LoaderManager.LoaderCallbacks<Cursor>, BreadCrumbView.Controller,
John Reckd3e4d5b2011-07-13 15:48:43 -070081 OnChildClickListener {
The Android Open Source Project0c908882009-03-03 19:32:16 -080082
Dave Tharp490ca7f2015-06-16 11:17:34 -070083 private static final String TAG = "BrowserBookmarksPage";
84
John Recke7c97de2011-05-27 14:42:43 -070085 public static class ExtraDragState {
86 public int childPosition;
87 public int groupPosition;
88 }
89
Jeff Hamilton84029622010-08-05 14:29:28 -050090 static final String LOGTAG = "browser";
Nicolas Catania095292f2010-03-15 09:00:14 -070091
John Reck71efc2b2011-05-09 16:54:28 -070092 static final int LOADER_ACCOUNTS = 1;
93 static final int LOADER_BOOKMARKS = 100;
Jeff Hamilton84029622010-08-05 14:29:28 -050094
Michael Kolb801ecb72010-08-25 12:57:38 -070095 static final String EXTRA_DISABLE_WINDOW = "disable_new_window";
John Reck4f61ee42011-08-22 16:31:14 -070096 static final String PREF_GROUP_STATE = "bbp_group_state";
Michael Kolb801ecb72010-08-25 12:57:38 -070097
John Reck71efc2b2011-05-09 16:54:28 -070098 static final String ACCOUNT_TYPE = "account_type";
99 static final String ACCOUNT_NAME = "account_name";
100
luxiaoldbe4a622013-07-19 17:14:06 +0800101 static final long DEFAULT_FOLDER_ID = -1;
102
John Reck608baa72010-11-24 10:32:28 -0800103 BookmarksPageCallbacks mCallbacks;
John Reck0ce8a942011-01-14 19:57:09 -0800104 View mRoot;
John Reck9db95292011-06-20 13:00:12 -0700105 BookmarkExpandableView mGrid;
Jeff Hamilton84029622010-08-05 14:29:28 -0500106 boolean mDisableNewWindow;
John Reck608baa72010-11-24 10:32:28 -0800107 boolean mEnableContextMenu = true;
Jeff Hamilton84029622010-08-05 14:29:28 -0500108 View mEmptyView;
John Reck608baa72010-11-24 10:32:28 -0800109 View mHeader;
John Reck71efc2b2011-05-09 16:54:28 -0700110 HashMap<Integer, BrowserBookmarksAdapter> mBookmarkAdapters = new HashMap<Integer, BrowserBookmarksAdapter>();
John Reck4f61ee42011-08-22 16:31:14 -0700111 JSONObject mState;
luxiaoldbe4a622013-07-19 17:14:06 +0800112 long mCurrentFolderId = BrowserProvider2.FIXED_ID_ROOT;
Michael Kolb370a4f32010-10-06 10:45:32 -0700113
Jeff Hamilton84029622010-08-05 14:29:28 -0500114 @Override
115 public Loader<Cursor> onCreateLoader(int id, Bundle args) {
John Reck71efc2b2011-05-09 16:54:28 -0700116 if (id == LOADER_ACCOUNTS) {
117 return new AccountsLoader(getActivity());
118 } else if (id >= LOADER_BOOKMARKS) {
119 String accountType = args.getString(ACCOUNT_TYPE);
120 String accountName = args.getString(ACCOUNT_NAME);
121 BookmarksLoader bl = new BookmarksLoader(getActivity(),
122 accountType, accountName);
123 return bl;
124 } else {
125 throw new UnsupportedOperationException("Unknown loader id " + id);
Jeff Hamilton84029622010-08-05 14:29:28 -0500126 }
Jeff Hamilton84029622010-08-05 14:29:28 -0500127 }
128
129 @Override
Jeff Hamiltondb90aa82010-09-16 03:38:04 -0500130 public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
John Reck71efc2b2011-05-09 16:54:28 -0700131 if (loader.getId() == LOADER_ACCOUNTS) {
132 LoaderManager lm = getLoaderManager();
133 int id = LOADER_BOOKMARKS;
134 while (cursor.moveToNext()) {
135 String accountName = cursor.getString(0);
136 String accountType = cursor.getString(1);
137 Bundle args = new Bundle();
138 args.putString(ACCOUNT_NAME, accountName);
139 args.putString(ACCOUNT_TYPE, accountType);
140 BrowserBookmarksAdapter adapter = new BrowserBookmarksAdapter(
John Reckaf991f92012-04-24 15:31:16 -0700141 getActivity());
John Reck71efc2b2011-05-09 16:54:28 -0700142 mBookmarkAdapters.put(id, adapter);
John Reck4f61ee42011-08-22 16:31:14 -0700143 boolean expand = true;
144 try {
145 expand = mState.getBoolean(accountName != null ? accountName
146 : BookmarkExpandableView.LOCAL_ACCOUNT_NAME);
147 } catch (JSONException e) {} // no state for accountName
148 mGrid.addAccount(accountName, adapter, expand);
John Reck71efc2b2011-05-09 16:54:28 -0700149 lm.restartLoader(id, args, this);
150 id++;
Jeff Hamiltondb90aa82010-09-16 03:38:04 -0500151 }
Sagar Dhawandde6e942015-07-22 11:55:52 -0700152 if (id == LOADER_BOOKMARKS){ // Didn't find any bookmarks
153 Bundle args = new Bundle();
154 args.putString(ACCOUNT_NAME, "null");
155 args.putString(ACCOUNT_TYPE, "null");
156 BrowserBookmarksAdapter adapter = new BrowserBookmarksAdapter(
157 getActivity());
158 mBookmarkAdapters.put(id, adapter);
159 boolean expand = true;
160 try {
161 expand = mState.getBoolean(BookmarkExpandableView.LOCAL_ACCOUNT_NAME);
162 } catch (JSONException e) {} // no state for accountName
163 mGrid.addAccount("null", adapter, expand);
164 lm.restartLoader(id, args, this);
165 }
John Reck71efc2b2011-05-09 16:54:28 -0700166 // TODO: Figure out what a reload of these means
167 // Currently, a reload is triggered whenever bookmarks change
168 // This is less than ideal
169 // It also causes UI flickering as a new adapter is created
170 // instead of re-using an existing one when the account_name is the
171 // same.
172 // For now, this is a one-shot load
173 getLoaderManager().destroyLoader(LOADER_ACCOUNTS);
174 } else if (loader.getId() >= LOADER_BOOKMARKS) {
175 BrowserBookmarksAdapter adapter = mBookmarkAdapters.get(loader.getId());
176 adapter.changeCursor(cursor);
luxiaoldbe4a622013-07-19 17:14:06 +0800177 if (adapter.getCount() != 0) {
178 mCurrentFolderId = adapter.getItem(0).getLong(BookmarksLoader.COLUMN_INDEX_PARENT);
179 }
Jeff Hamiltondb90aa82010-09-16 03:38:04 -0500180 }
Jeff Hamilton84029622010-08-05 14:29:28 -0500181 }
182
John Reck522a4382011-01-26 13:23:47 -0800183 @Override
Dianne Hackborn39772c82010-12-16 00:43:54 -0800184 public void onLoaderReset(Loader<Cursor> loader) {
John Reck3ad8d5c2012-04-23 14:50:09 -0700185 if (loader.getId() >= LOADER_BOOKMARKS) {
186 BrowserBookmarksAdapter adapter = mBookmarkAdapters.get(loader.getId());
187 adapter.changeCursor(null);
188 }
Dianne Hackborn39772c82010-12-16 00:43:54 -0800189 }
190
The Android Open Source Project0c908882009-03-03 19:32:16 -0800191 @Override
192 public boolean onContextItemSelected(MenuItem item) {
John Reck54ed3aa2011-08-19 15:16:05 -0700193 if (!(item.getMenuInfo() instanceof BookmarkContextMenuInfo)) {
194 return false;
195 }
196 BookmarkContextMenuInfo i = (BookmarkContextMenuInfo) item.getMenuInfo();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800197 // If we have no menu info, we can't tell which item was selected.
198 if (i == null) {
Leon Scrogginsc8cae082010-11-03 18:51:46 -0400199 return false;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800200 }
Nicolas Catania095292f2010-03-15 09:00:14 -0700201
John Recke7c97de2011-05-27 14:42:43 -0700202 if (handleContextItem(item.getItemId(), i.groupPosition, i.childPosition)) {
203 return true;
204 }
205 return super.onContextItemSelected(item);
206 }
207
208 public boolean handleContextItem(int itemId, int groupPosition,
209 int childPosition) {
210 final Activity activity = getActivity();
211 BrowserBookmarksAdapter adapter = getChildAdapter(groupPosition);
212
213 switch (itemId) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800214 case R.id.open_context_menu_id:
John Recke7c97de2011-05-27 14:42:43 -0700215 loadUrl(adapter, childPosition);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800216 break;
Dave Tharp490ca7f2015-06-16 11:17:34 -0700217 case R.id.folder_edit_context_menu_id:
The Android Open Source Project0c908882009-03-03 19:32:16 -0800218 case R.id.edit_context_menu_id:
John Recke7c97de2011-05-27 14:42:43 -0700219 editBookmark(adapter, childPosition);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800220 break;
221 case R.id.shortcut_context_menu_id:
John Recke7c97de2011-05-27 14:42:43 -0700222 Cursor c = adapter.getItem(childPosition);
John Reck608baa72010-11-24 10:32:28 -0800223 activity.sendBroadcast(createShortcutIntent(getActivity(), c));
The Android Open Source Project0c908882009-03-03 19:32:16 -0800224 break;
Dave Tharp490ca7f2015-06-16 11:17:34 -0700225 case R.id.folder_delete_context_menu_id:
The Android Open Source Project0c908882009-03-03 19:32:16 -0800226 case R.id.delete_context_menu_id:
John Recke7c97de2011-05-27 14:42:43 -0700227 displayRemoveBookmarkDialog(adapter, childPosition);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800228 break;
229 case R.id.new_window_context_menu_id:
John Recke7c97de2011-05-27 14:42:43 -0700230 openInNewWindow(adapter, childPosition);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800231 break;
Jeff Hamilton84029622010-08-05 14:29:28 -0500232 case R.id.share_link_context_menu_id: {
John Recke7c97de2011-05-27 14:42:43 -0700233 Cursor cursor = adapter.getItem(childPosition);
Michael Kolb8233fac2010-10-26 16:08:53 -0700234 Controller.sharePage(activity,
Jeff Hamilton84029622010-08-05 14:29:28 -0500235 cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE),
236 cursor.getString(BookmarksLoader.COLUMN_INDEX_URL),
237 getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_FAVICON),
238 getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_THUMBNAIL));
The Android Open Source Project0c908882009-03-03 19:32:16 -0800239 break;
Jeff Hamilton84029622010-08-05 14:29:28 -0500240 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800241 case R.id.copy_url_context_menu_id:
John Recke7c97de2011-05-27 14:42:43 -0700242 copy(getUrl(adapter, childPosition));
Leon Scrogginsfeb941d2009-05-28 17:27:38 -0400243 break;
Jeff Hamilton84029622010-08-05 14:29:28 -0500244 case R.id.homepage_context_menu_id: {
John Recke7c97de2011-05-27 14:42:43 -0700245 BrowserSettings.getInstance().setHomePage(getUrl(adapter, childPosition));
Jeff Hamilton64144e42010-08-18 16:31:59 -0500246 Toast.makeText(activity, R.string.homepage_set, Toast.LENGTH_LONG).show();
Leon Scrogginsfeb941d2009-05-28 17:27:38 -0400247 break;
Jeff Hamilton84029622010-08-05 14:29:28 -0500248 }
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400249 // Only for the Most visited page
Jeff Hamilton84029622010-08-05 14:29:28 -0500250 case R.id.save_to_bookmarks_menu_id: {
John Recke7c97de2011-05-27 14:42:43 -0700251 Cursor cursor = adapter.getItem(childPosition);
Jeff Hamilton84029622010-08-05 14:29:28 -0500252 String name = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE);
253 String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL);
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400254 // If the site is bookmarked, the item becomes remove from
255 // bookmarks.
Jeff Hamilton64144e42010-08-18 16:31:59 -0500256 Bookmarks.removeFromBookmarks(activity, activity.getContentResolver(), url, name);
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400257 break;
Jeff Hamilton84029622010-08-05 14:29:28 -0500258 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800259 default:
John Recke7c97de2011-05-27 14:42:43 -0700260 return false;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800261 }
262 return true;
263 }
264
John Reck608baa72010-11-24 10:32:28 -0800265 static Bitmap getBitmap(Cursor cursor, int columnIndex) {
John Reckf94abcf2011-10-10 15:33:48 -0700266 return getBitmap(cursor, columnIndex, null);
267 }
268
269 static ThreadLocal<Options> sOptions = new ThreadLocal<Options>() {
270 @Override
271 protected Options initialValue() {
272 return new Options();
273 };
274 };
275 static Bitmap getBitmap(Cursor cursor, int columnIndex, Bitmap inBitmap) {
Jeff Hamilton84029622010-08-05 14:29:28 -0500276 byte[] data = cursor.getBlob(columnIndex);
277 if (data == null) {
278 return null;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800279 }
John Reckf94abcf2011-10-10 15:33:48 -0700280 Options opts = sOptions.get();
281 opts.inBitmap = inBitmap;
282 opts.inSampleSize = 1;
283 opts.inScaled = false;
284 try {
285 return BitmapFactory.decodeByteArray(data, 0, data.length, opts);
286 } catch (IllegalArgumentException ex) {
287 // Failed to re-use bitmap, create a new one
288 return BitmapFactory.decodeByteArray(data, 0, data.length);
289 }
Jeff Hamilton84029622010-08-05 14:29:28 -0500290 }
291
John Reckc8490812010-11-22 14:15:36 -0800292 private MenuItem.OnMenuItemClickListener mContextItemClickListener =
293 new MenuItem.OnMenuItemClickListener() {
294 @Override
295 public boolean onMenuItemClick(MenuItem item) {
296 return onContextItemSelected(item);
297 }
298 };
299
Jeff Hamilton84029622010-08-05 14:29:28 -0500300 @Override
301 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
John Reck71efc2b2011-05-09 16:54:28 -0700302 BookmarkContextMenuInfo info = (BookmarkContextMenuInfo) menuInfo;
303 BrowserBookmarksAdapter adapter = getChildAdapter(info.groupPosition);
304 Cursor cursor = adapter.getItem(info.childPosition);
John Reck1cebb442010-12-10 12:02:16 -0800305 if (!canEdit(cursor)) {
306 return;
307 }
Leon Scroggins5e8a40f2010-09-27 17:13:35 -0400308 boolean isFolder
309 = cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0;
Dave Tharp490ca7f2015-06-16 11:17:34 -0700310 boolean isMdmElem = ManagedBookmarksRestriction.getInstance().mDb.
311 isMdmElement(cursor.getLong(BookmarksLoader.COLUMN_INDEX_ID));
Dave Tharp9a082b12015-06-19 08:46:57 -0700312 boolean isMdmEditRestricted = EditBookmarksRestriction.getInstance().isEnabled();
Michael Kolb801ecb72010-08-25 12:57:38 -0700313
Jeff Hamilton64144e42010-08-18 16:31:59 -0500314 final Activity activity = getActivity();
315 MenuInflater inflater = activity.getMenuInflater();
Jeff Hamilton84029622010-08-05 14:29:28 -0500316 inflater.inflate(R.menu.bookmarkscontext, menu);
John Reckc8490812010-11-22 14:15:36 -0800317 if (isFolder) {
318 menu.setGroupVisible(R.id.FOLDER_CONTEXT_MENU, true);
Dave Tharp9a082b12015-06-19 08:46:57 -0700319 if(isMdmElem || isMdmEditRestricted) {
Dave Tharp490ca7f2015-06-16 11:17:34 -0700320 menu.findItem(R.id.folder_edit_context_menu_id).setEnabled(false);
321 menu.findItem(R.id.folder_delete_context_menu_id).setEnabled(false);
322 }
John Reckc8490812010-11-22 14:15:36 -0800323 } else {
324 menu.setGroupVisible(R.id.BOOKMARK_CONTEXT_MENU, true);
325 if (mDisableNewWindow) {
326 menu.findItem(R.id.new_window_context_menu_id).setVisible(false);
327 }
Dave Tharp9a082b12015-06-19 08:46:57 -0700328 if(isMdmElem || isMdmEditRestricted) {
Dave Tharp490ca7f2015-06-16 11:17:34 -0700329 menu.findItem(R.id.edit_context_menu_id).setEnabled(false);
330 menu.findItem(R.id.delete_context_menu_id).setEnabled(false);
331 }
Jeff Hamilton84029622010-08-05 14:29:28 -0500332 }
John Reckc8490812010-11-22 14:15:36 -0800333 BookmarkItem header = new BookmarkItem(activity);
John Reck83c01512011-09-09 11:14:16 -0700334 header.setEnableScrolling(true);
Dave Tharp490ca7f2015-06-16 11:17:34 -0700335 populateBookmarkItem(cursor, header, isFolder, isMdmElem);
John Reckc8490812010-11-22 14:15:36 -0800336 menu.setHeaderView(header);
Jeff Hamilton84029622010-08-05 14:29:28 -0500337
John Reckc8490812010-11-22 14:15:36 -0800338 int count = menu.size();
339 for (int i = 0; i < count; i++) {
340 menu.getItem(i).setOnMenuItemClickListener(mContextItemClickListener);
Jeff Hamilton84029622010-08-05 14:29:28 -0500341 }
Jeff Hamilton84029622010-08-05 14:29:28 -0500342 }
343
John Reck1cebb442010-12-10 12:02:16 -0800344 boolean canEdit(Cursor c) {
John Reckd18ac4b2012-04-12 17:27:34 -0700345 int type = c.getInt(BookmarksLoader.COLUMN_INDEX_TYPE);
346 return type == BrowserContract.Bookmarks.BOOKMARK_TYPE_BOOKMARK
347 || type == BrowserContract.Bookmarks.BOOKMARK_TYPE_FOLDER;
John Reck1cebb442010-12-10 12:02:16 -0800348 }
349
Dave Tharp0eaec992015-07-08 10:58:04 -0700350 public static Bitmap overlayBookmarkBitmap(Context context, Bitmap origImage, int overlayResId,
351 int containerWidth, int containerHeight,
352 float overlayScale, int overlayOffsetY,
353 int overlayMarginX) {
Dave Tharp490ca7f2015-06-16 11:17:34 -0700354 if (origImage == null) {
355 Log.e(TAG, "Orig Image is null!");
356 return origImage;
357 }
Dave Tharp0eaec992015-07-08 10:58:04 -0700358
Dave Tharp490ca7f2015-06-16 11:17:34 -0700359 // Get metrics for incoming bitmap
360 int origWidth = origImage.getWidth();
361 int origHeight = origImage.getHeight();
362
Dave Tharp0eaec992015-07-08 10:58:04 -0700363 // Compute final overlay scale factor based on container size
364 float willScale, overlayScaleFactor;
365 if (Math.abs(containerWidth - origWidth) > Math.abs(containerHeight - origHeight)) {
366 willScale = (float) containerWidth / (float) origWidth;
367 }
368 else {
369 willScale = (float) containerHeight / (float) origHeight;
370 }
371 overlayScaleFactor = overlayScale / willScale;
372
Dave Tharp490ca7f2015-06-16 11:17:34 -0700373 // Load the bitmap for the badge
374 Bitmap srcOverlay = BitmapFactory.decodeResource(context.getResources(), overlayResId);
Dave Tharp490ca7f2015-06-16 11:17:34 -0700375 if (srcOverlay == null) {
376 Log.e(TAG, "Overlay bitmap creation failed");
377 return origImage;
378 }
379
380 // Scale the badge
381 float fx = (float) srcOverlay.getWidth() * overlayScaleFactor;
382 float fy = (float) srcOverlay.getHeight() * overlayScaleFactor;
Sagar Dhawana59c22c2015-07-22 10:27:03 -0700383 Bitmap scaledOverlay = null;
384 try {
385 scaledOverlay = Bitmap.createScaledBitmap(srcOverlay, (int) fx, (int) fy, true);
386 } catch (IllegalArgumentException exception) {
387 Log.e(TAG, "Scaled bitmap creation failed" + exception.getMessage());
388 }
389
Dave Tharp490ca7f2015-06-16 11:17:34 -0700390 if (scaledOverlay == null) {
391 srcOverlay.recycle();
392 Runtime.getRuntime().gc();
Dave Tharp490ca7f2015-06-16 11:17:34 -0700393 return origImage;
394 }
395
396 // Create the bitmap we are compositing into
Sagar Dhawana59c22c2015-07-22 10:27:03 -0700397 Bitmap overlaid = null;
398 try {
399 overlaid = Bitmap.createBitmap(origWidth, origHeight, Bitmap.Config.ARGB_8888);
400 } catch (IllegalArgumentException exception) {
401 Log.e(TAG, "Composite bitmap creation failed" + exception.getMessage());
402 }
403
Dave Tharp490ca7f2015-06-16 11:17:34 -0700404 if (overlaid == null) {
405 srcOverlay.recycle();
406 scaledOverlay.recycle();
407 Runtime.getRuntime().gc();
Dave Tharp490ca7f2015-06-16 11:17:34 -0700408 return origImage;
409 }
410
411 // Do the overlay
412 Canvas comboImage = new Canvas(overlaid);
413 comboImage.drawBitmap(origImage, 0, 0, null);
414
Dave Tharp0eaec992015-07-08 10:58:04 -0700415 // align overlay to right edge. Vertical alignment
Dave Tharp9a082b12015-06-19 08:46:57 -0700416 // determined by overlayOffsetY
Dave Tharp490ca7f2015-06-16 11:17:34 -0700417 comboImage.drawBitmap(scaledOverlay,
Dave Tharp0eaec992015-07-08 10:58:04 -0700418 (origWidth - scaledOverlay.getWidth()) - (overlayMarginX / willScale),
419 (overlayOffsetY / willScale),
Dave Tharp490ca7f2015-06-16 11:17:34 -0700420 null);
421
422 // Clean up our bitmaps
423 srcOverlay.recycle();
424 scaledOverlay.recycle();
425 Runtime.getRuntime().gc();
426
427 return overlaid;
428 }
429
Dave Tharp9a082b12015-06-19 08:46:57 -0700430 private void populateBookmarkItem(Cursor cursor, BookmarkItem item,
431 boolean isFolder, boolean isMdmElem) {
Jeff Hamilton84029622010-08-05 14:29:28 -0500432 item.setName(cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE));
Dave Tharp9a082b12015-06-19 08:46:57 -0700433
434 // Fetch appropriate bitmap
435 Bitmap bitmap;
John Reckc8490812010-11-22 14:15:36 -0800436 if (isFolder) {
437 item.setUrl(null);
Dave Tharp9a082b12015-06-19 08:46:57 -0700438 bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_deco_folder_normal);
439 }
440 else {
John Reckc8490812010-11-22 14:15:36 -0800441 String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL);
442 item.setUrl(url);
Dave Tharp9a082b12015-06-19 08:46:57 -0700443 bitmap = getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_FAVICON);
444 if (null == bitmap) {
445 bitmap = BitmapFactory.decodeResource(getResources(),
446 R.drawable.ic_deco_favicon_normal);
Dave Tharp490ca7f2015-06-16 11:17:34 -0700447 }
Dave Tharp9a082b12015-06-19 08:46:57 -0700448 }
449
Dave Tharp0eaec992015-07-08 10:58:04 -0700450 // if mdm element or edit bookmark restriction enforced, overlay an indicator
451 if (isMdmElem || EditBookmarksRestriction.getInstance().isEnabled()) {
452 int containerSize = getResources().
453 getDimensionPixelSize(R.dimen.bookmark_widget_favicon_size); // it's square!
Dave Tharp9a082b12015-06-19 08:46:57 -0700454 if (isMdmElem) {
Dave Tharp0eaec992015-07-08 10:58:04 -0700455 bitmap = overlayBookmarkBitmap(getActivity(), bitmap,
456 R.drawable.img_deco_mdm_badge_bright,
457 containerSize, containerSize, 0.25f, 40, 0);
Dave Tharp9a082b12015-06-19 08:46:57 -0700458 }
459 else if (EditBookmarksRestriction.getInstance().isEnabled()) {
Dave Tharp0eaec992015-07-08 10:58:04 -0700460 bitmap = overlayBookmarkBitmap(getActivity(), bitmap,
461 R.drawable.ic_deco_secure,
462 containerSize, containerSize, 0.75f, 0, 0);
Dave Tharp9a082b12015-06-19 08:46:57 -0700463 }
464 }
465
466 // Set the bitmap
467 item.setFavicon(bitmap);
468 if (isFolder) {
469 new LookupBookmarkCount(getActivity(), item)
470 .execute(cursor.getLong(BookmarksLoader.COLUMN_INDEX_ID));
Jeff Hamilton84029622010-08-05 14:29:28 -0500471 }
Jeff Hamilton84029622010-08-05 14:29:28 -0500472 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800473
474 /**
475 * Create a new BrowserBookmarksPage.
Nicolas Catania095292f2010-03-15 09:00:14 -0700476 */
The Android Open Source Project0c908882009-03-03 19:32:16 -0800477 @Override
Jeff Hamilton64144e42010-08-18 16:31:59 -0500478 public void onCreate(Bundle icicle) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800479 super.onCreate(icicle);
John Reck4f61ee42011-08-22 16:31:14 -0700480 SharedPreferences prefs = BrowserSettings.getInstance().getPreferences();
481 try {
482 mState = new JSONObject(prefs.getString(PREF_GROUP_STATE, "{}"));
483 } catch (JSONException e) {
484 // Parse failed, clear preference and start with empty state
485 prefs.edit().remove(PREF_GROUP_STATE).apply();
486 mState = new JSONObject();
487 }
Jeff Hamilton64144e42010-08-18 16:31:59 -0500488 Bundle args = getArguments();
Leon Scrogginsbc922852010-10-22 12:15:27 -0400489 mDisableNewWindow = args == null ? false : args.getBoolean(EXTRA_DISABLE_WINDOW, false);
John Reck2d963a22011-08-10 15:53:07 -0700490 if (mCallbacks == null && getActivity() instanceof CombinedBookmarksCallbacks) {
491 mCallbacks = new CombinedBookmarksCallbackWrapper(
492 (CombinedBookmarksCallbacks) getActivity());
493 }
Tarun Nainani87a86682015-02-05 11:47:35 -0800494 if (mCallbacks == null) {
495 View cb = getActivity().getWindow().getDecorView().findViewById(R.id.combo_view_container);
496 if (cb != null && cb instanceof CombinedBookmarksCallbacks) {
497 mCallbacks = new CombinedBookmarksCallbackWrapper(
498 (CombinedBookmarksCallbacks) cb);
499 }
500 }
Jeff Hamilton64144e42010-08-18 16:31:59 -0500501 }
Leon Scrogginsd87f85e2009-08-18 14:13:31 -0400502
John Reck4f61ee42011-08-22 16:31:14 -0700503 @Override
504 public void onPause() {
505 super.onPause();
506 try {
507 mState = mGrid.saveGroupState();
508 // Save state
509 SharedPreferences prefs = BrowserSettings.getInstance().getPreferences();
510 prefs.edit()
511 .putString(PREF_GROUP_STATE, mState.toString())
512 .apply();
513 } catch (JSONException e) {
514 // Not critical, ignore
515 }
516 }
517
John Reck2d963a22011-08-10 15:53:07 -0700518 private static class CombinedBookmarksCallbackWrapper
519 implements BookmarksPageCallbacks {
520
521 private CombinedBookmarksCallbacks mCombinedCallback;
522
523 private CombinedBookmarksCallbackWrapper(CombinedBookmarksCallbacks cb) {
524 mCombinedCallback = cb;
525 }
526
527 @Override
528 public boolean onOpenInNewWindow(String... urls) {
529 mCombinedCallback.openInNewTab(urls);
530 return true;
531 }
532
533 @Override
534 public boolean onBookmarkSelected(Cursor c, boolean isFolder) {
535 if (isFolder) {
536 return false;
537 }
538 mCombinedCallback.openUrl(BrowserBookmarksPage.getUrl(c));
539 return true;
540 }
541 };
542
Jeff Hamilton64144e42010-08-18 16:31:59 -0500543 @Override
Jeff Hamilton64144e42010-08-18 16:31:59 -0500544 public View onCreateView(LayoutInflater inflater, ViewGroup container,
545 Bundle savedInstanceState) {
Pankaj Garg49b79252014-11-07 17:33:41 -0800546 final Activity activity = getActivity();
John Reck0ce8a942011-01-14 19:57:09 -0800547 mRoot = inflater.inflate(R.layout.bookmarks, container, false);
548 mEmptyView = mRoot.findViewById(android.R.id.empty);
Leon Scrogginsd87f85e2009-08-18 14:13:31 -0400549
John Reck9db95292011-06-20 13:00:12 -0700550 mGrid = (BookmarkExpandableView) mRoot.findViewById(R.id.grid);
John Reck71efc2b2011-05-09 16:54:28 -0700551 mGrid.setOnChildClickListener(this);
552 mGrid.setColumnWidthFromLayout(R.layout.bookmark_thumbnail);
553 mGrid.setBreadcrumbController(this);
John Reck608baa72010-11-24 10:32:28 -0800554 setEnableContextMenu(mEnableContextMenu);
555
Pankaj Garg49b79252014-11-07 17:33:41 -0800556 Button btn = (Button) mRoot.findViewById(R.id.add_bookmark_button);
557 btn.setOnClickListener(new View.OnClickListener() {
558 @Override
559 public void onClick(View view) {
Dave Tharp490ca7f2015-06-16 11:17:34 -0700560 ManagedBookmarksRestriction mbr = ManagedBookmarksRestriction.getInstance();
Dave Tharp9a082b12015-06-19 08:46:57 -0700561 if ((mbr.isEnabled() && mbr.mDb.isMdmElement(mCurrentFolderId)) ||
562 EditBookmarksRestriction.getInstance().isEnabled()) {
563 Toast.makeText(getActivity().getApplicationContext(),
564 R.string.mdm_managed_alert, Toast.LENGTH_SHORT).show();
Dave Tharp490ca7f2015-06-16 11:17:34 -0700565 }
566 else {
567 Intent intent = new Intent(activity, AddBookmarkPage.class);
568 intent.putExtra(BrowserContract.Bookmarks.URL, "http://");
569 intent.putExtra(BrowserContract.Bookmarks.TITLE, "");
570 intent.putExtra(BrowserContract.Bookmarks.PARENT, mCurrentFolderId);
571 activity.startActivity(intent);
572 }
Pankaj Garg49b79252014-11-07 17:33:41 -0800573 }
574 });
Dave Tharp9a082b12015-06-19 08:46:57 -0700575 EditBookmarksRestriction.getInstance().registerControl(btn);
Pankaj Garg49b79252014-11-07 17:33:41 -0800576
577 btn = (Button) mRoot.findViewById(R.id.new_bmfolder_button);
578 btn.setOnClickListener(new View.OnClickListener() {
579 @Override
580 public void onClick(View view) {
Dave Tharp490ca7f2015-06-16 11:17:34 -0700581 ManagedBookmarksRestriction mbr = ManagedBookmarksRestriction.getInstance();
Dave Tharp9a082b12015-06-19 08:46:57 -0700582 if ((mbr.isEnabled() && mbr.mDb.isMdmElement(mCurrentFolderId)) ||
583 EditBookmarksRestriction.getInstance().isEnabled()) {
584 Toast.makeText(getActivity().getApplicationContext(),
585 R.string.mdm_managed_alert, Toast.LENGTH_SHORT).show();
Dave Tharp490ca7f2015-06-16 11:17:34 -0700586 }
587 else {
588 Intent intent = new Intent(activity, AddBookmarkFolder.class);
589 intent.putExtra(BrowserContract.Bookmarks.PARENT, mCurrentFolderId);
590 activity.startActivity(intent);
591 }
Pankaj Garg49b79252014-11-07 17:33:41 -0800592 }
593 });
Dave Tharp9a082b12015-06-19 08:46:57 -0700594 EditBookmarksRestriction.getInstance().registerControl(btn);
Pankaj Garg49b79252014-11-07 17:33:41 -0800595
Jeff Hamiltondb90aa82010-09-16 03:38:04 -0500596 // Start the loaders
597 LoaderManager lm = getLoaderManager();
John Reck71efc2b2011-05-09 16:54:28 -0700598 lm.restartLoader(LOADER_ACCOUNTS, null, this);
Jeff Hamilton84029622010-08-05 14:29:28 -0500599
Dany Rybnikovbcd37da2015-04-20 11:43:15 +0300600 if (!BrowserSettings.getInstance().isPowerSaveModeEnabled()) {
601 //Notify about anticipated network activity
602 NetworkServices.hintUpcomingUserActivity();
603 }
Dany Rybnikovb80159e2014-06-23 09:16:09 +0300604
Dave Tharp9a082b12015-06-19 08:46:57 -0700605 EditBookmarksRestriction.getInstance().registerView(mGrid);
606
John Reck0ce8a942011-01-14 19:57:09 -0800607 return mRoot;
Jeff Hamilton64144e42010-08-18 16:31:59 -0500608 }
Michael Kolb801ecb72010-08-25 12:57:38 -0700609
John Reck608baa72010-11-24 10:32:28 -0800610 @Override
611 public void onDestroyView() {
612 super.onDestroyView();
John Reck71efc2b2011-05-09 16:54:28 -0700613 mGrid.setBreadcrumbController(null);
John Reckc3c46d72011-09-06 16:17:34 -0700614 mGrid.clearAccounts();
John Reck71efc2b2011-05-09 16:54:28 -0700615 LoaderManager lm = getLoaderManager();
616 lm.destroyLoader(LOADER_ACCOUNTS);
617 for (int id : mBookmarkAdapters.keySet()) {
Tarun Nainaniebdf18e2014-07-09 19:35:30 -0700618 mBookmarkAdapters.get(id).quitThread();
John Reck71efc2b2011-05-09 16:54:28 -0700619 lm.destroyLoader(id);
John Reck608baa72010-11-24 10:32:28 -0800620 }
John Reck71efc2b2011-05-09 16:54:28 -0700621 mBookmarkAdapters.clear();
Dave Tharp9a082b12015-06-19 08:46:57 -0700622
623 EditBookmarksRestriction.getInstance().registerView(null);
John Reck71efc2b2011-05-09 16:54:28 -0700624 }
625
626 private BrowserBookmarksAdapter getChildAdapter(int groupPosition) {
John Reck9db95292011-06-20 13:00:12 -0700627 return mGrid.getChildAdapter(groupPosition);
John Reck71efc2b2011-05-09 16:54:28 -0700628 }
629
630 private BreadCrumbView getBreadCrumbs(int groupPosition) {
John Reck9db95292011-06-20 13:00:12 -0700631 return mGrid.getBreadCrumbs(groupPosition);
Nicolas Catania095292f2010-03-15 09:00:14 -0700632 }
633
Jeff Hamilton84029622010-08-05 14:29:28 -0500634 @Override
John Reck71efc2b2011-05-09 16:54:28 -0700635 public boolean onChildClick(ExpandableListView parent, View v,
636 int groupPosition, int childPosition, long id) {
637 BrowserBookmarksAdapter adapter = getChildAdapter(groupPosition);
638 Cursor cursor = adapter.getItem(childPosition);
John Reck608baa72010-11-24 10:32:28 -0800639 boolean isFolder = cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0;
640 if (mCallbacks != null &&
641 mCallbacks.onBookmarkSelected(cursor, isFolder)) {
John Reck71efc2b2011-05-09 16:54:28 -0700642 return true;
Ben Murdoch328ea872009-09-16 13:33:29 +0100643 }
644
John Reck608baa72010-11-24 10:32:28 -0800645 if (isFolder) {
Michael Kolb370a4f32010-10-06 10:45:32 -0700646 String title = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE);
Jeff Hamilton84029622010-08-05 14:29:28 -0500647 Uri uri = ContentUris.withAppendedId(
648 BrowserContract.Bookmarks.CONTENT_URI_DEFAULT_FOLDER, id);
John Reck71efc2b2011-05-09 16:54:28 -0700649 BreadCrumbView crumbs = getBreadCrumbs(groupPosition);
650 if (crumbs != null) {
Michael Kolb370a4f32010-10-06 10:45:32 -0700651 // update crumbs
John Reck71efc2b2011-05-09 16:54:28 -0700652 crumbs.pushView(title, uri);
John Reckcece1fe2011-09-13 08:47:17 -0700653 crumbs.setVisibility(View.VISIBLE);
luxiaoldbe4a622013-07-19 17:14:06 +0800654 Object data = crumbs.getTopData();
655 mCurrentFolderId = (data != null ? ContentUris.parseId((Uri) data)
656 : DEFAULT_FOLDER_ID);
Michael Kolb370a4f32010-10-06 10:45:32 -0700657 }
John Reck71efc2b2011-05-09 16:54:28 -0700658 loadFolder(groupPosition, uri);
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400659 }
John Reck71efc2b2011-05-09 16:54:28 -0700660 return true;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800661 }
662
John Reck608baa72010-11-24 10:32:28 -0800663 /* package */ static Intent createShortcutIntent(Context context, Cursor cursor) {
Jeff Hamilton84029622010-08-05 14:29:28 -0500664 String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL);
Michael Kolbccaa8962010-10-20 17:03:10 -0700665 String title = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE);
Jeff Hamilton84029622010-08-05 14:29:28 -0500666 Bitmap touchIcon = getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_TOUCH_ICON);
667 Bitmap favicon = getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_FAVICON);
John Reck608baa72010-11-24 10:32:28 -0800668 return BookmarkUtils.createAddToHomeIntent(context, url, title, touchIcon, favicon);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800669 }
670
John Reck71efc2b2011-05-09 16:54:28 -0700671 private void loadUrl(BrowserBookmarksAdapter adapter, int position) {
672 if (mCallbacks != null && adapter != null) {
673 mCallbacks.onBookmarkSelected(adapter.getItem(position), false);
John Reck608baa72010-11-24 10:32:28 -0800674 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800675 }
676
John Reck71efc2b2011-05-09 16:54:28 -0700677 private void openInNewWindow(BrowserBookmarksAdapter adapter, int position) {
John Reck608baa72010-11-24 10:32:28 -0800678 if (mCallbacks != null) {
John Reck71efc2b2011-05-09 16:54:28 -0700679 Cursor c = adapter.getItem(position);
John Reck1b3c66e2011-01-11 13:20:32 -0800680 boolean isFolder = c.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) == 1;
681 if (isFolder) {
682 long id = c.getLong(BookmarksLoader.COLUMN_INDEX_ID);
683 new OpenAllInTabsTask(id).execute();
684 } else {
John Reckd3e4d5b2011-07-13 15:48:43 -0700685 mCallbacks.onOpenInNewWindow(BrowserBookmarksPage.getUrl(c));
John Reck1b3c66e2011-01-11 13:20:32 -0800686 }
John Reck608baa72010-11-24 10:32:28 -0800687 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800688 }
Nicolas Catania095292f2010-03-15 09:00:14 -0700689
John Reck1b3c66e2011-01-11 13:20:32 -0800690 class OpenAllInTabsTask extends AsyncTask<Void, Void, Cursor> {
691 long mFolderId;
692 public OpenAllInTabsTask(long id) {
693 mFolderId = id;
694 }
695
696 @Override
697 protected Cursor doInBackground(Void... params) {
698 Context c = getActivity();
699 if (c == null) return null;
700 return c.getContentResolver().query(BookmarkUtils.getBookmarksUri(c),
701 BookmarksLoader.PROJECTION, BrowserContract.Bookmarks.PARENT + "=?",
702 new String[] { Long.toString(mFolderId) }, null);
703 }
704
705 @Override
706 protected void onPostExecute(Cursor result) {
John Reckd3e4d5b2011-07-13 15:48:43 -0700707 if (mCallbacks != null && result.getCount() > 0) {
708 String[] urls = new String[result.getCount()];
709 int i = 0;
John Reck1b3c66e2011-01-11 13:20:32 -0800710 while (result.moveToNext()) {
John Reckd3e4d5b2011-07-13 15:48:43 -0700711 urls[i++] = BrowserBookmarksPage.getUrl(result);
John Reck1b3c66e2011-01-11 13:20:32 -0800712 }
John Reckd3e4d5b2011-07-13 15:48:43 -0700713 mCallbacks.onOpenInNewWindow(urls);
John Reck1b3c66e2011-01-11 13:20:32 -0800714 }
715 }
716
717 }
718
John Reck71efc2b2011-05-09 16:54:28 -0700719 private void editBookmark(BrowserBookmarksAdapter adapter, int position) {
Jeff Hamilton64144e42010-08-18 16:31:59 -0500720 Intent intent = new Intent(getActivity(), AddBookmarkPage.class);
John Reck71efc2b2011-05-09 16:54:28 -0700721 Cursor cursor = adapter.getItem(position);
Jeff Hamilton84029622010-08-05 14:29:28 -0500722 Bundle item = new Bundle();
Michael Kolbbef7a752010-08-25 17:11:35 -0700723 item.putString(BrowserContract.Bookmarks.TITLE,
Jeff Hamilton84029622010-08-05 14:29:28 -0500724 cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE));
Michael Kolbbef7a752010-08-25 17:11:35 -0700725 item.putString(BrowserContract.Bookmarks.URL,
Jeff Hamilton84029622010-08-05 14:29:28 -0500726 cursor.getString(BookmarksLoader.COLUMN_INDEX_URL));
727 byte[] data = cursor.getBlob(BookmarksLoader.COLUMN_INDEX_FAVICON);
728 if (data != null) {
Michael Kolbbef7a752010-08-25 17:11:35 -0700729 item.putParcelable(BrowserContract.Bookmarks.FAVICON,
Jeff Hamilton84029622010-08-05 14:29:28 -0500730 BitmapFactory.decodeByteArray(data, 0, data.length));
731 }
John Reckc8490812010-11-22 14:15:36 -0800732 item.putLong(BrowserContract.Bookmarks._ID,
733 cursor.getLong(BookmarksLoader.COLUMN_INDEX_ID));
Leon Scroggins III052ce662010-09-13 14:44:16 -0400734 item.putLong(BrowserContract.Bookmarks.PARENT,
735 cursor.getLong(BookmarksLoader.COLUMN_INDEX_PARENT));
John Reckc8490812010-11-22 14:15:36 -0800736 intent.putExtra(AddBookmarkPage.EXTRA_EDIT_BOOKMARK, item);
737 intent.putExtra(AddBookmarkPage.EXTRA_IS_FOLDER,
738 cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) == 1);
739 startActivity(intent);
Jeff Hamilton84029622010-08-05 14:29:28 -0500740 }
741
John Reck71efc2b2011-05-09 16:54:28 -0700742 private void displayRemoveBookmarkDialog(BrowserBookmarksAdapter adapter,
743 int position) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800744 // Put up a dialog asking if the user really wants to
745 // delete the bookmark
John Reck71efc2b2011-05-09 16:54:28 -0700746 Cursor cursor = adapter.getItem(position);
Leon Scroggins75630672011-01-13 17:56:15 -0500747 long id = cursor.getLong(BookmarksLoader.COLUMN_INDEX_ID);
748 String title = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE);
Jeff Hamilton64144e42010-08-18 16:31:59 -0500749 Context context = getActivity();
Pankaj Garg634bf432015-07-13 09:54:21 -0700750 BookmarkUtils.displayRemoveBookmarkDialog(id, title, context, null,
751 (cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) == 1));
The Android Open Source Project0c908882009-03-03 19:32:16 -0800752 }
753
John Reck71efc2b2011-05-09 16:54:28 -0700754 private String getUrl(BrowserBookmarksAdapter adapter, int position) {
755 return getUrl(adapter.getItem(position));
John Reck608baa72010-11-24 10:32:28 -0800756 }
757
758 /* package */ static String getUrl(Cursor c) {
759 return c.getString(BookmarksLoader.COLUMN_INDEX_URL);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800760 }
Michael Kolb801ecb72010-08-25 12:57:38 -0700761
The Android Open Source Project0c908882009-03-03 19:32:16 -0800762 private void copy(CharSequence text) {
Jeff Hamilton64144e42010-08-18 16:31:59 -0500763 ClipboardManager cm = (ClipboardManager) getActivity().getSystemService(
764 Context.CLIPBOARD_SERVICE);
Dianne Hackbornbf1d10a2011-01-17 12:29:51 -0800765 cm.setPrimaryClip(ClipData.newRawUri(null, Uri.parse(text.toString())));
The Android Open Source Project0c908882009-03-03 19:32:16 -0800766 }
Michael Kolb370a4f32010-10-06 10:45:32 -0700767
John Reckb3417f02011-01-14 11:01:05 -0800768 @Override
John Reckb3417f02011-01-14 11:01:05 -0800769 public void onConfigurationChanged(Configuration newConfig) {
770 super.onConfigurationChanged(newConfig);
771 Resources res = getActivity().getResources();
John Reck71efc2b2011-05-09 16:54:28 -0700772 mGrid.setColumnWidthFromLayout(R.layout.bookmark_thumbnail);
John Reck0ce8a942011-01-14 19:57:09 -0800773 int paddingTop = (int) res.getDimension(R.dimen.combo_paddingTop);
John Reckf3828cd2011-06-14 17:21:55 -0700774 mRoot.setPadding(0, paddingTop, 0, 0);
John Reckb3417f02011-01-14 11:01:05 -0800775 }
776
John Reck608baa72010-11-24 10:32:28 -0800777 /**
778 * BreadCrumb controller callback
779 */
780 @Override
John Reck71efc2b2011-05-09 16:54:28 -0700781 public void onTop(BreadCrumbView view, int level, Object data) {
782 int groupPosition = (Integer) view.getTag(R.id.group_position);
John Reck89f73c12010-12-01 10:10:14 -0800783 Uri uri = (Uri) data;
784 if (uri == null) {
785 // top level
786 uri = BrowserContract.Bookmarks.CONTENT_URI_DEFAULT_FOLDER;
787 }
John Reck71efc2b2011-05-09 16:54:28 -0700788 loadFolder(groupPosition, uri);
John Reckcece1fe2011-09-13 08:47:17 -0700789 if (level <= 1) {
790 view.setVisibility(View.GONE);
791 } else {
792 view.setVisibility(View.VISIBLE);
793 }
John Reck89f73c12010-12-01 10:10:14 -0800794 }
795
796 /**
797 * @param uri
798 */
John Reck71efc2b2011-05-09 16:54:28 -0700799 private void loadFolder(int groupPosition, Uri uri) {
John Reck89f73c12010-12-01 10:10:14 -0800800 LoaderManager manager = getLoaderManager();
John Reck71efc2b2011-05-09 16:54:28 -0700801 // This assumes groups are ordered the same as loaders
802 BookmarksLoader loader = (BookmarksLoader) ((Loader<?>)
803 manager.getLoader(LOADER_BOOKMARKS + groupPosition));
John Reck89f73c12010-12-01 10:10:14 -0800804 loader.setUri(uri);
805 loader.forceLoad();
John Reck608baa72010-11-24 10:32:28 -0800806 }
807
John Reck608baa72010-11-24 10:32:28 -0800808 public void setCallbackListener(BookmarksPageCallbacks callbackListener) {
809 mCallbacks = callbackListener;
810 }
811
812 public void setEnableContextMenu(boolean enable) {
813 mEnableContextMenu = enable;
814 if (mGrid != null) {
815 if (mEnableContextMenu) {
816 registerForContextMenu(mGrid);
817 } else {
818 unregisterForContextMenu(mGrid);
819 mGrid.setLongClickable(false);
820 }
821 }
John Reck608baa72010-11-24 10:32:28 -0800822 }
John Reckc8490812010-11-22 14:15:36 -0800823
824 private static class LookupBookmarkCount extends AsyncTask<Long, Void, Integer> {
825 Context mContext;
826 BookmarkItem mHeader;
827
828 public LookupBookmarkCount(Context context, BookmarkItem header) {
Ben Murdoch914c5592011-08-01 13:58:47 +0100829 mContext = context.getApplicationContext();
John Reckc8490812010-11-22 14:15:36 -0800830 mHeader = header;
831 }
832
833 @Override
834 protected Integer doInBackground(Long... params) {
835 if (params.length != 1) {
836 throw new IllegalArgumentException("Missing folder id!");
837 }
838 Uri uri = BookmarkUtils.getBookmarksUri(mContext);
Axesh R. Ajmera632e5a02014-11-13 09:52:46 -0800839 Cursor c = null;
840 try {
841 c = mContext.getContentResolver().query(uri,
842 null, BrowserContract.Bookmarks.PARENT + "=?",
843 new String[] {params[0].toString()}, null);
844 return c.getCount();
845 } finally {
846 if (c != null) {
847 c.close();
848 }
849 }
John Reckc8490812010-11-22 14:15:36 -0800850 }
851
852 @Override
853 protected void onPostExecute(Integer result) {
854 if (result > 0) {
855 mHeader.setUrl(mContext.getString(R.string.contextheader_folder_bookmarkcount,
856 result));
857 } else if (result == 0) {
858 mHeader.setUrl(mContext.getString(R.string.contextheader_folder_empty));
859 }
860 }
861 }
John Reck89f73c12010-12-01 10:10:14 -0800862
John Reck71efc2b2011-05-09 16:54:28 -0700863 static class AccountsLoader extends CursorLoader {
John Reck89f73c12010-12-01 10:10:14 -0800864
John Reck71efc2b2011-05-09 16:54:28 -0700865 static String[] ACCOUNTS_PROJECTION = new String[] {
866 Accounts.ACCOUNT_NAME,
867 Accounts.ACCOUNT_TYPE
868 };
John Reck89f73c12010-12-01 10:10:14 -0800869
John Reck71efc2b2011-05-09 16:54:28 -0700870 public AccountsLoader(Context context) {
John Reck1e9815d2011-08-08 17:45:05 -0700871 super(context, Accounts.CONTENT_URI
872 .buildUpon()
873 .appendQueryParameter(BrowserProvider2.PARAM_ALLOW_EMPTY_ACCOUNTS, "false")
874 .build(),
875 ACCOUNTS_PROJECTION, null, null, null);
John Reck89f73c12010-12-01 10:10:14 -0800876 }
John Reck522a4382011-01-26 13:23:47 -0800877
John Reck522a4382011-01-26 13:23:47 -0800878 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800879}