blob: 935bdc6070333aea7a14f2be85268efd1089f55a [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 }
John Reck71efc2b2011-05-09 16:54:28 -0700152 // TODO: Figure out what a reload of these means
153 // Currently, a reload is triggered whenever bookmarks change
154 // This is less than ideal
155 // It also causes UI flickering as a new adapter is created
156 // instead of re-using an existing one when the account_name is the
157 // same.
158 // For now, this is a one-shot load
159 getLoaderManager().destroyLoader(LOADER_ACCOUNTS);
160 } else if (loader.getId() >= LOADER_BOOKMARKS) {
161 BrowserBookmarksAdapter adapter = mBookmarkAdapters.get(loader.getId());
162 adapter.changeCursor(cursor);
luxiaoldbe4a622013-07-19 17:14:06 +0800163 if (adapter.getCount() != 0) {
164 mCurrentFolderId = adapter.getItem(0).getLong(BookmarksLoader.COLUMN_INDEX_PARENT);
165 }
Jeff Hamiltondb90aa82010-09-16 03:38:04 -0500166 }
Jeff Hamilton84029622010-08-05 14:29:28 -0500167 }
168
John Reck522a4382011-01-26 13:23:47 -0800169 @Override
Dianne Hackborn39772c82010-12-16 00:43:54 -0800170 public void onLoaderReset(Loader<Cursor> loader) {
John Reck3ad8d5c2012-04-23 14:50:09 -0700171 if (loader.getId() >= LOADER_BOOKMARKS) {
172 BrowserBookmarksAdapter adapter = mBookmarkAdapters.get(loader.getId());
173 adapter.changeCursor(null);
174 }
Dianne Hackborn39772c82010-12-16 00:43:54 -0800175 }
176
The Android Open Source Project0c908882009-03-03 19:32:16 -0800177 @Override
178 public boolean onContextItemSelected(MenuItem item) {
John Reck54ed3aa2011-08-19 15:16:05 -0700179 if (!(item.getMenuInfo() instanceof BookmarkContextMenuInfo)) {
180 return false;
181 }
182 BookmarkContextMenuInfo i = (BookmarkContextMenuInfo) item.getMenuInfo();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800183 // If we have no menu info, we can't tell which item was selected.
184 if (i == null) {
Leon Scrogginsc8cae082010-11-03 18:51:46 -0400185 return false;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800186 }
Nicolas Catania095292f2010-03-15 09:00:14 -0700187
John Recke7c97de2011-05-27 14:42:43 -0700188 if (handleContextItem(item.getItemId(), i.groupPosition, i.childPosition)) {
189 return true;
190 }
191 return super.onContextItemSelected(item);
192 }
193
194 public boolean handleContextItem(int itemId, int groupPosition,
195 int childPosition) {
196 final Activity activity = getActivity();
197 BrowserBookmarksAdapter adapter = getChildAdapter(groupPosition);
198
199 switch (itemId) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800200 case R.id.open_context_menu_id:
John Recke7c97de2011-05-27 14:42:43 -0700201 loadUrl(adapter, childPosition);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800202 break;
Dave Tharp490ca7f2015-06-16 11:17:34 -0700203 case R.id.folder_edit_context_menu_id:
The Android Open Source Project0c908882009-03-03 19:32:16 -0800204 case R.id.edit_context_menu_id:
John Recke7c97de2011-05-27 14:42:43 -0700205 editBookmark(adapter, childPosition);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800206 break;
207 case R.id.shortcut_context_menu_id:
John Recke7c97de2011-05-27 14:42:43 -0700208 Cursor c = adapter.getItem(childPosition);
John Reck608baa72010-11-24 10:32:28 -0800209 activity.sendBroadcast(createShortcutIntent(getActivity(), c));
The Android Open Source Project0c908882009-03-03 19:32:16 -0800210 break;
Dave Tharp490ca7f2015-06-16 11:17:34 -0700211 case R.id.folder_delete_context_menu_id:
The Android Open Source Project0c908882009-03-03 19:32:16 -0800212 case R.id.delete_context_menu_id:
John Recke7c97de2011-05-27 14:42:43 -0700213 displayRemoveBookmarkDialog(adapter, childPosition);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800214 break;
215 case R.id.new_window_context_menu_id:
John Recke7c97de2011-05-27 14:42:43 -0700216 openInNewWindow(adapter, childPosition);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800217 break;
Jeff Hamilton84029622010-08-05 14:29:28 -0500218 case R.id.share_link_context_menu_id: {
John Recke7c97de2011-05-27 14:42:43 -0700219 Cursor cursor = adapter.getItem(childPosition);
Michael Kolb8233fac2010-10-26 16:08:53 -0700220 Controller.sharePage(activity,
Jeff Hamilton84029622010-08-05 14:29:28 -0500221 cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE),
222 cursor.getString(BookmarksLoader.COLUMN_INDEX_URL),
223 getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_FAVICON),
224 getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_THUMBNAIL));
The Android Open Source Project0c908882009-03-03 19:32:16 -0800225 break;
Jeff Hamilton84029622010-08-05 14:29:28 -0500226 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800227 case R.id.copy_url_context_menu_id:
John Recke7c97de2011-05-27 14:42:43 -0700228 copy(getUrl(adapter, childPosition));
Leon Scrogginsfeb941d2009-05-28 17:27:38 -0400229 break;
Jeff Hamilton84029622010-08-05 14:29:28 -0500230 case R.id.homepage_context_menu_id: {
John Recke7c97de2011-05-27 14:42:43 -0700231 BrowserSettings.getInstance().setHomePage(getUrl(adapter, childPosition));
Jeff Hamilton64144e42010-08-18 16:31:59 -0500232 Toast.makeText(activity, R.string.homepage_set, Toast.LENGTH_LONG).show();
Leon Scrogginsfeb941d2009-05-28 17:27:38 -0400233 break;
Jeff Hamilton84029622010-08-05 14:29:28 -0500234 }
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400235 // Only for the Most visited page
Jeff Hamilton84029622010-08-05 14:29:28 -0500236 case R.id.save_to_bookmarks_menu_id: {
John Recke7c97de2011-05-27 14:42:43 -0700237 Cursor cursor = adapter.getItem(childPosition);
Jeff Hamilton84029622010-08-05 14:29:28 -0500238 String name = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE);
239 String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL);
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400240 // If the site is bookmarked, the item becomes remove from
241 // bookmarks.
Jeff Hamilton64144e42010-08-18 16:31:59 -0500242 Bookmarks.removeFromBookmarks(activity, activity.getContentResolver(), url, name);
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400243 break;
Jeff Hamilton84029622010-08-05 14:29:28 -0500244 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800245 default:
John Recke7c97de2011-05-27 14:42:43 -0700246 return false;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800247 }
248 return true;
249 }
250
John Reck608baa72010-11-24 10:32:28 -0800251 static Bitmap getBitmap(Cursor cursor, int columnIndex) {
John Reckf94abcf2011-10-10 15:33:48 -0700252 return getBitmap(cursor, columnIndex, null);
253 }
254
255 static ThreadLocal<Options> sOptions = new ThreadLocal<Options>() {
256 @Override
257 protected Options initialValue() {
258 return new Options();
259 };
260 };
261 static Bitmap getBitmap(Cursor cursor, int columnIndex, Bitmap inBitmap) {
Jeff Hamilton84029622010-08-05 14:29:28 -0500262 byte[] data = cursor.getBlob(columnIndex);
263 if (data == null) {
264 return null;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800265 }
John Reckf94abcf2011-10-10 15:33:48 -0700266 Options opts = sOptions.get();
267 opts.inBitmap = inBitmap;
268 opts.inSampleSize = 1;
269 opts.inScaled = false;
270 try {
271 return BitmapFactory.decodeByteArray(data, 0, data.length, opts);
272 } catch (IllegalArgumentException ex) {
273 // Failed to re-use bitmap, create a new one
274 return BitmapFactory.decodeByteArray(data, 0, data.length);
275 }
Jeff Hamilton84029622010-08-05 14:29:28 -0500276 }
277
John Reckc8490812010-11-22 14:15:36 -0800278 private MenuItem.OnMenuItemClickListener mContextItemClickListener =
279 new MenuItem.OnMenuItemClickListener() {
280 @Override
281 public boolean onMenuItemClick(MenuItem item) {
282 return onContextItemSelected(item);
283 }
284 };
285
Jeff Hamilton84029622010-08-05 14:29:28 -0500286 @Override
287 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
John Reck71efc2b2011-05-09 16:54:28 -0700288 BookmarkContextMenuInfo info = (BookmarkContextMenuInfo) menuInfo;
289 BrowserBookmarksAdapter adapter = getChildAdapter(info.groupPosition);
290 Cursor cursor = adapter.getItem(info.childPosition);
John Reck1cebb442010-12-10 12:02:16 -0800291 if (!canEdit(cursor)) {
292 return;
293 }
Leon Scroggins5e8a40f2010-09-27 17:13:35 -0400294 boolean isFolder
295 = cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0;
Dave Tharp490ca7f2015-06-16 11:17:34 -0700296 boolean isMdmElem = ManagedBookmarksRestriction.getInstance().mDb.
297 isMdmElement(cursor.getLong(BookmarksLoader.COLUMN_INDEX_ID));
Dave Tharp9a082b12015-06-19 08:46:57 -0700298 boolean isMdmEditRestricted = EditBookmarksRestriction.getInstance().isEnabled();
Michael Kolb801ecb72010-08-25 12:57:38 -0700299
Jeff Hamilton64144e42010-08-18 16:31:59 -0500300 final Activity activity = getActivity();
301 MenuInflater inflater = activity.getMenuInflater();
Jeff Hamilton84029622010-08-05 14:29:28 -0500302 inflater.inflate(R.menu.bookmarkscontext, menu);
John Reckc8490812010-11-22 14:15:36 -0800303 if (isFolder) {
304 menu.setGroupVisible(R.id.FOLDER_CONTEXT_MENU, true);
Dave Tharp9a082b12015-06-19 08:46:57 -0700305 if(isMdmElem || isMdmEditRestricted) {
Dave Tharp490ca7f2015-06-16 11:17:34 -0700306 menu.findItem(R.id.folder_edit_context_menu_id).setEnabled(false);
307 menu.findItem(R.id.folder_delete_context_menu_id).setEnabled(false);
308 }
John Reckc8490812010-11-22 14:15:36 -0800309 } else {
310 menu.setGroupVisible(R.id.BOOKMARK_CONTEXT_MENU, true);
311 if (mDisableNewWindow) {
312 menu.findItem(R.id.new_window_context_menu_id).setVisible(false);
313 }
Dave Tharp9a082b12015-06-19 08:46:57 -0700314 if(isMdmElem || isMdmEditRestricted) {
Dave Tharp490ca7f2015-06-16 11:17:34 -0700315 menu.findItem(R.id.edit_context_menu_id).setEnabled(false);
316 menu.findItem(R.id.delete_context_menu_id).setEnabled(false);
317 }
Jeff Hamilton84029622010-08-05 14:29:28 -0500318 }
John Reckc8490812010-11-22 14:15:36 -0800319 BookmarkItem header = new BookmarkItem(activity);
John Reck83c01512011-09-09 11:14:16 -0700320 header.setEnableScrolling(true);
Dave Tharp490ca7f2015-06-16 11:17:34 -0700321 populateBookmarkItem(cursor, header, isFolder, isMdmElem);
John Reckc8490812010-11-22 14:15:36 -0800322 menu.setHeaderView(header);
Jeff Hamilton84029622010-08-05 14:29:28 -0500323
John Reckc8490812010-11-22 14:15:36 -0800324 int count = menu.size();
325 for (int i = 0; i < count; i++) {
326 menu.getItem(i).setOnMenuItemClickListener(mContextItemClickListener);
Jeff Hamilton84029622010-08-05 14:29:28 -0500327 }
Jeff Hamilton84029622010-08-05 14:29:28 -0500328 }
329
John Reck1cebb442010-12-10 12:02:16 -0800330 boolean canEdit(Cursor c) {
John Reckd18ac4b2012-04-12 17:27:34 -0700331 int type = c.getInt(BookmarksLoader.COLUMN_INDEX_TYPE);
332 return type == BrowserContract.Bookmarks.BOOKMARK_TYPE_BOOKMARK
333 || type == BrowserContract.Bookmarks.BOOKMARK_TYPE_FOLDER;
John Reck1cebb442010-12-10 12:02:16 -0800334 }
335
Dave Tharp0eaec992015-07-08 10:58:04 -0700336 public static Bitmap overlayBookmarkBitmap(Context context, Bitmap origImage, int overlayResId,
337 int containerWidth, int containerHeight,
338 float overlayScale, int overlayOffsetY,
339 int overlayMarginX) {
Dave Tharp490ca7f2015-06-16 11:17:34 -0700340 if (origImage == null) {
341 Log.e(TAG, "Orig Image is null!");
342 return origImage;
343 }
Dave Tharp0eaec992015-07-08 10:58:04 -0700344
Dave Tharp490ca7f2015-06-16 11:17:34 -0700345 // Get metrics for incoming bitmap
346 int origWidth = origImage.getWidth();
347 int origHeight = origImage.getHeight();
348
Dave Tharp0eaec992015-07-08 10:58:04 -0700349 // Compute final overlay scale factor based on container size
350 float willScale, overlayScaleFactor;
351 if (Math.abs(containerWidth - origWidth) > Math.abs(containerHeight - origHeight)) {
352 willScale = (float) containerWidth / (float) origWidth;
353 }
354 else {
355 willScale = (float) containerHeight / (float) origHeight;
356 }
357 overlayScaleFactor = overlayScale / willScale;
358
Dave Tharp490ca7f2015-06-16 11:17:34 -0700359 // Load the bitmap for the badge
360 Bitmap srcOverlay = BitmapFactory.decodeResource(context.getResources(), overlayResId);
Dave Tharp490ca7f2015-06-16 11:17:34 -0700361 if (srcOverlay == null) {
362 Log.e(TAG, "Overlay bitmap creation failed");
363 return origImage;
364 }
365
366 // Scale the badge
367 float fx = (float) srcOverlay.getWidth() * overlayScaleFactor;
368 float fy = (float) srcOverlay.getHeight() * overlayScaleFactor;
369 Bitmap scaledOverlay = Bitmap.createScaledBitmap(srcOverlay, (int) fx, (int) fy, true);
370 if (scaledOverlay == null) {
371 srcOverlay.recycle();
372 Runtime.getRuntime().gc();
373 Log.e(TAG, "Scaled bitmap creation failed");
374 return origImage;
375 }
376
377 // Create the bitmap we are compositing into
378 Bitmap overlaid = Bitmap.createBitmap(origWidth, origHeight, Bitmap.Config.ARGB_8888);
379 if (overlaid == null) {
380 srcOverlay.recycle();
381 scaledOverlay.recycle();
382 Runtime.getRuntime().gc();
383 Log.e(TAG, "Composite bitmap creation failed");
384 return origImage;
385 }
386
387 // Do the overlay
388 Canvas comboImage = new Canvas(overlaid);
389 comboImage.drawBitmap(origImage, 0, 0, null);
390
Dave Tharp0eaec992015-07-08 10:58:04 -0700391 // align overlay to right edge. Vertical alignment
Dave Tharp9a082b12015-06-19 08:46:57 -0700392 // determined by overlayOffsetY
Dave Tharp490ca7f2015-06-16 11:17:34 -0700393 comboImage.drawBitmap(scaledOverlay,
Dave Tharp0eaec992015-07-08 10:58:04 -0700394 (origWidth - scaledOverlay.getWidth()) - (overlayMarginX / willScale),
395 (overlayOffsetY / willScale),
Dave Tharp490ca7f2015-06-16 11:17:34 -0700396 null);
397
398 // Clean up our bitmaps
399 srcOverlay.recycle();
400 scaledOverlay.recycle();
401 Runtime.getRuntime().gc();
402
403 return overlaid;
404 }
405
Dave Tharp9a082b12015-06-19 08:46:57 -0700406 private void populateBookmarkItem(Cursor cursor, BookmarkItem item,
407 boolean isFolder, boolean isMdmElem) {
Jeff Hamilton84029622010-08-05 14:29:28 -0500408 item.setName(cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE));
Dave Tharp9a082b12015-06-19 08:46:57 -0700409
410 // Fetch appropriate bitmap
411 Bitmap bitmap;
John Reckc8490812010-11-22 14:15:36 -0800412 if (isFolder) {
413 item.setUrl(null);
Dave Tharp9a082b12015-06-19 08:46:57 -0700414 bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_deco_folder_normal);
415 }
416 else {
John Reckc8490812010-11-22 14:15:36 -0800417 String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL);
418 item.setUrl(url);
Dave Tharp9a082b12015-06-19 08:46:57 -0700419 bitmap = getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_FAVICON);
420 if (null == bitmap) {
421 bitmap = BitmapFactory.decodeResource(getResources(),
422 R.drawable.ic_deco_favicon_normal);
Dave Tharp490ca7f2015-06-16 11:17:34 -0700423 }
Dave Tharp9a082b12015-06-19 08:46:57 -0700424 }
425
Dave Tharp0eaec992015-07-08 10:58:04 -0700426 // if mdm element or edit bookmark restriction enforced, overlay an indicator
427 if (isMdmElem || EditBookmarksRestriction.getInstance().isEnabled()) {
428 int containerSize = getResources().
429 getDimensionPixelSize(R.dimen.bookmark_widget_favicon_size); // it's square!
Dave Tharp9a082b12015-06-19 08:46:57 -0700430 if (isMdmElem) {
Dave Tharp0eaec992015-07-08 10:58:04 -0700431 bitmap = overlayBookmarkBitmap(getActivity(), bitmap,
432 R.drawable.img_deco_mdm_badge_bright,
433 containerSize, containerSize, 0.25f, 40, 0);
Dave Tharp9a082b12015-06-19 08:46:57 -0700434 }
435 else if (EditBookmarksRestriction.getInstance().isEnabled()) {
Dave Tharp0eaec992015-07-08 10:58:04 -0700436 bitmap = overlayBookmarkBitmap(getActivity(), bitmap,
437 R.drawable.ic_deco_secure,
438 containerSize, containerSize, 0.75f, 0, 0);
Dave Tharp9a082b12015-06-19 08:46:57 -0700439 }
440 }
441
442 // Set the bitmap
443 item.setFavicon(bitmap);
444 if (isFolder) {
445 new LookupBookmarkCount(getActivity(), item)
446 .execute(cursor.getLong(BookmarksLoader.COLUMN_INDEX_ID));
Jeff Hamilton84029622010-08-05 14:29:28 -0500447 }
Jeff Hamilton84029622010-08-05 14:29:28 -0500448 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800449
450 /**
451 * Create a new BrowserBookmarksPage.
Nicolas Catania095292f2010-03-15 09:00:14 -0700452 */
The Android Open Source Project0c908882009-03-03 19:32:16 -0800453 @Override
Jeff Hamilton64144e42010-08-18 16:31:59 -0500454 public void onCreate(Bundle icicle) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800455 super.onCreate(icicle);
John Reck4f61ee42011-08-22 16:31:14 -0700456 SharedPreferences prefs = BrowserSettings.getInstance().getPreferences();
457 try {
458 mState = new JSONObject(prefs.getString(PREF_GROUP_STATE, "{}"));
459 } catch (JSONException e) {
460 // Parse failed, clear preference and start with empty state
461 prefs.edit().remove(PREF_GROUP_STATE).apply();
462 mState = new JSONObject();
463 }
Jeff Hamilton64144e42010-08-18 16:31:59 -0500464 Bundle args = getArguments();
Leon Scrogginsbc922852010-10-22 12:15:27 -0400465 mDisableNewWindow = args == null ? false : args.getBoolean(EXTRA_DISABLE_WINDOW, false);
John Reck2d963a22011-08-10 15:53:07 -0700466 if (mCallbacks == null && getActivity() instanceof CombinedBookmarksCallbacks) {
467 mCallbacks = new CombinedBookmarksCallbackWrapper(
468 (CombinedBookmarksCallbacks) getActivity());
469 }
Tarun Nainani87a86682015-02-05 11:47:35 -0800470 if (mCallbacks == null) {
471 View cb = getActivity().getWindow().getDecorView().findViewById(R.id.combo_view_container);
472 if (cb != null && cb instanceof CombinedBookmarksCallbacks) {
473 mCallbacks = new CombinedBookmarksCallbackWrapper(
474 (CombinedBookmarksCallbacks) cb);
475 }
476 }
Jeff Hamilton64144e42010-08-18 16:31:59 -0500477 }
Leon Scrogginsd87f85e2009-08-18 14:13:31 -0400478
John Reck4f61ee42011-08-22 16:31:14 -0700479 @Override
480 public void onPause() {
481 super.onPause();
482 try {
483 mState = mGrid.saveGroupState();
484 // Save state
485 SharedPreferences prefs = BrowserSettings.getInstance().getPreferences();
486 prefs.edit()
487 .putString(PREF_GROUP_STATE, mState.toString())
488 .apply();
489 } catch (JSONException e) {
490 // Not critical, ignore
491 }
492 }
493
John Reck2d963a22011-08-10 15:53:07 -0700494 private static class CombinedBookmarksCallbackWrapper
495 implements BookmarksPageCallbacks {
496
497 private CombinedBookmarksCallbacks mCombinedCallback;
498
499 private CombinedBookmarksCallbackWrapper(CombinedBookmarksCallbacks cb) {
500 mCombinedCallback = cb;
501 }
502
503 @Override
504 public boolean onOpenInNewWindow(String... urls) {
505 mCombinedCallback.openInNewTab(urls);
506 return true;
507 }
508
509 @Override
510 public boolean onBookmarkSelected(Cursor c, boolean isFolder) {
511 if (isFolder) {
512 return false;
513 }
514 mCombinedCallback.openUrl(BrowserBookmarksPage.getUrl(c));
515 return true;
516 }
517 };
518
Jeff Hamilton64144e42010-08-18 16:31:59 -0500519 @Override
Jeff Hamilton64144e42010-08-18 16:31:59 -0500520 public View onCreateView(LayoutInflater inflater, ViewGroup container,
521 Bundle savedInstanceState) {
Pankaj Garg49b79252014-11-07 17:33:41 -0800522 final Activity activity = getActivity();
John Reck0ce8a942011-01-14 19:57:09 -0800523 mRoot = inflater.inflate(R.layout.bookmarks, container, false);
524 mEmptyView = mRoot.findViewById(android.R.id.empty);
Leon Scrogginsd87f85e2009-08-18 14:13:31 -0400525
John Reck9db95292011-06-20 13:00:12 -0700526 mGrid = (BookmarkExpandableView) mRoot.findViewById(R.id.grid);
John Reck71efc2b2011-05-09 16:54:28 -0700527 mGrid.setOnChildClickListener(this);
528 mGrid.setColumnWidthFromLayout(R.layout.bookmark_thumbnail);
529 mGrid.setBreadcrumbController(this);
John Reck608baa72010-11-24 10:32:28 -0800530 setEnableContextMenu(mEnableContextMenu);
531
Pankaj Garg49b79252014-11-07 17:33:41 -0800532 Button btn = (Button) mRoot.findViewById(R.id.add_bookmark_button);
533 btn.setOnClickListener(new View.OnClickListener() {
534 @Override
535 public void onClick(View view) {
Dave Tharp490ca7f2015-06-16 11:17:34 -0700536 ManagedBookmarksRestriction mbr = ManagedBookmarksRestriction.getInstance();
Dave Tharp9a082b12015-06-19 08:46:57 -0700537 if ((mbr.isEnabled() && mbr.mDb.isMdmElement(mCurrentFolderId)) ||
538 EditBookmarksRestriction.getInstance().isEnabled()) {
539 Toast.makeText(getActivity().getApplicationContext(),
540 R.string.mdm_managed_alert, Toast.LENGTH_SHORT).show();
Dave Tharp490ca7f2015-06-16 11:17:34 -0700541 }
542 else {
543 Intent intent = new Intent(activity, AddBookmarkPage.class);
544 intent.putExtra(BrowserContract.Bookmarks.URL, "http://");
545 intent.putExtra(BrowserContract.Bookmarks.TITLE, "");
546 intent.putExtra(BrowserContract.Bookmarks.PARENT, mCurrentFolderId);
547 activity.startActivity(intent);
548 }
Pankaj Garg49b79252014-11-07 17:33:41 -0800549 }
550 });
Dave Tharp9a082b12015-06-19 08:46:57 -0700551 EditBookmarksRestriction.getInstance().registerControl(btn);
Pankaj Garg49b79252014-11-07 17:33:41 -0800552
553 btn = (Button) mRoot.findViewById(R.id.new_bmfolder_button);
554 btn.setOnClickListener(new View.OnClickListener() {
555 @Override
556 public void onClick(View view) {
Dave Tharp490ca7f2015-06-16 11:17:34 -0700557 ManagedBookmarksRestriction mbr = ManagedBookmarksRestriction.getInstance();
Dave Tharp9a082b12015-06-19 08:46:57 -0700558 if ((mbr.isEnabled() && mbr.mDb.isMdmElement(mCurrentFolderId)) ||
559 EditBookmarksRestriction.getInstance().isEnabled()) {
560 Toast.makeText(getActivity().getApplicationContext(),
561 R.string.mdm_managed_alert, Toast.LENGTH_SHORT).show();
Dave Tharp490ca7f2015-06-16 11:17:34 -0700562 }
563 else {
564 Intent intent = new Intent(activity, AddBookmarkFolder.class);
565 intent.putExtra(BrowserContract.Bookmarks.PARENT, mCurrentFolderId);
566 activity.startActivity(intent);
567 }
Pankaj Garg49b79252014-11-07 17:33:41 -0800568 }
569 });
Dave Tharp9a082b12015-06-19 08:46:57 -0700570 EditBookmarksRestriction.getInstance().registerControl(btn);
Pankaj Garg49b79252014-11-07 17:33:41 -0800571
Jeff Hamiltondb90aa82010-09-16 03:38:04 -0500572 // Start the loaders
573 LoaderManager lm = getLoaderManager();
John Reck71efc2b2011-05-09 16:54:28 -0700574 lm.restartLoader(LOADER_ACCOUNTS, null, this);
Jeff Hamilton84029622010-08-05 14:29:28 -0500575
Dany Rybnikovbcd37da2015-04-20 11:43:15 +0300576 if (!BrowserSettings.getInstance().isPowerSaveModeEnabled()) {
577 //Notify about anticipated network activity
578 NetworkServices.hintUpcomingUserActivity();
579 }
Dany Rybnikovb80159e2014-06-23 09:16:09 +0300580
Dave Tharp9a082b12015-06-19 08:46:57 -0700581 EditBookmarksRestriction.getInstance().registerView(mGrid);
582
John Reck0ce8a942011-01-14 19:57:09 -0800583 return mRoot;
Jeff Hamilton64144e42010-08-18 16:31:59 -0500584 }
Michael Kolb801ecb72010-08-25 12:57:38 -0700585
John Reck608baa72010-11-24 10:32:28 -0800586 @Override
587 public void onDestroyView() {
588 super.onDestroyView();
John Reck71efc2b2011-05-09 16:54:28 -0700589 mGrid.setBreadcrumbController(null);
John Reckc3c46d72011-09-06 16:17:34 -0700590 mGrid.clearAccounts();
John Reck71efc2b2011-05-09 16:54:28 -0700591 LoaderManager lm = getLoaderManager();
592 lm.destroyLoader(LOADER_ACCOUNTS);
593 for (int id : mBookmarkAdapters.keySet()) {
Tarun Nainaniebdf18e2014-07-09 19:35:30 -0700594 mBookmarkAdapters.get(id).quitThread();
John Reck71efc2b2011-05-09 16:54:28 -0700595 lm.destroyLoader(id);
John Reck608baa72010-11-24 10:32:28 -0800596 }
John Reck71efc2b2011-05-09 16:54:28 -0700597 mBookmarkAdapters.clear();
Dave Tharp9a082b12015-06-19 08:46:57 -0700598
599 EditBookmarksRestriction.getInstance().registerView(null);
John Reck71efc2b2011-05-09 16:54:28 -0700600 }
601
602 private BrowserBookmarksAdapter getChildAdapter(int groupPosition) {
John Reck9db95292011-06-20 13:00:12 -0700603 return mGrid.getChildAdapter(groupPosition);
John Reck71efc2b2011-05-09 16:54:28 -0700604 }
605
606 private BreadCrumbView getBreadCrumbs(int groupPosition) {
John Reck9db95292011-06-20 13:00:12 -0700607 return mGrid.getBreadCrumbs(groupPosition);
Nicolas Catania095292f2010-03-15 09:00:14 -0700608 }
609
Jeff Hamilton84029622010-08-05 14:29:28 -0500610 @Override
John Reck71efc2b2011-05-09 16:54:28 -0700611 public boolean onChildClick(ExpandableListView parent, View v,
612 int groupPosition, int childPosition, long id) {
613 BrowserBookmarksAdapter adapter = getChildAdapter(groupPosition);
614 Cursor cursor = adapter.getItem(childPosition);
John Reck608baa72010-11-24 10:32:28 -0800615 boolean isFolder = cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0;
616 if (mCallbacks != null &&
617 mCallbacks.onBookmarkSelected(cursor, isFolder)) {
John Reck71efc2b2011-05-09 16:54:28 -0700618 return true;
Ben Murdoch328ea872009-09-16 13:33:29 +0100619 }
620
John Reck608baa72010-11-24 10:32:28 -0800621 if (isFolder) {
Michael Kolb370a4f32010-10-06 10:45:32 -0700622 String title = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE);
Jeff Hamilton84029622010-08-05 14:29:28 -0500623 Uri uri = ContentUris.withAppendedId(
624 BrowserContract.Bookmarks.CONTENT_URI_DEFAULT_FOLDER, id);
John Reck71efc2b2011-05-09 16:54:28 -0700625 BreadCrumbView crumbs = getBreadCrumbs(groupPosition);
626 if (crumbs != null) {
Michael Kolb370a4f32010-10-06 10:45:32 -0700627 // update crumbs
John Reck71efc2b2011-05-09 16:54:28 -0700628 crumbs.pushView(title, uri);
John Reckcece1fe2011-09-13 08:47:17 -0700629 crumbs.setVisibility(View.VISIBLE);
luxiaoldbe4a622013-07-19 17:14:06 +0800630 Object data = crumbs.getTopData();
631 mCurrentFolderId = (data != null ? ContentUris.parseId((Uri) data)
632 : DEFAULT_FOLDER_ID);
Michael Kolb370a4f32010-10-06 10:45:32 -0700633 }
John Reck71efc2b2011-05-09 16:54:28 -0700634 loadFolder(groupPosition, uri);
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400635 }
John Reck71efc2b2011-05-09 16:54:28 -0700636 return true;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800637 }
638
John Reck608baa72010-11-24 10:32:28 -0800639 /* package */ static Intent createShortcutIntent(Context context, Cursor cursor) {
Jeff Hamilton84029622010-08-05 14:29:28 -0500640 String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL);
Michael Kolbccaa8962010-10-20 17:03:10 -0700641 String title = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE);
Jeff Hamilton84029622010-08-05 14:29:28 -0500642 Bitmap touchIcon = getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_TOUCH_ICON);
643 Bitmap favicon = getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_FAVICON);
John Reck608baa72010-11-24 10:32:28 -0800644 return BookmarkUtils.createAddToHomeIntent(context, url, title, touchIcon, favicon);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800645 }
646
John Reck71efc2b2011-05-09 16:54:28 -0700647 private void loadUrl(BrowserBookmarksAdapter adapter, int position) {
648 if (mCallbacks != null && adapter != null) {
649 mCallbacks.onBookmarkSelected(adapter.getItem(position), false);
John Reck608baa72010-11-24 10:32:28 -0800650 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800651 }
652
John Reck71efc2b2011-05-09 16:54:28 -0700653 private void openInNewWindow(BrowserBookmarksAdapter adapter, int position) {
John Reck608baa72010-11-24 10:32:28 -0800654 if (mCallbacks != null) {
John Reck71efc2b2011-05-09 16:54:28 -0700655 Cursor c = adapter.getItem(position);
John Reck1b3c66e2011-01-11 13:20:32 -0800656 boolean isFolder = c.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) == 1;
657 if (isFolder) {
658 long id = c.getLong(BookmarksLoader.COLUMN_INDEX_ID);
659 new OpenAllInTabsTask(id).execute();
660 } else {
John Reckd3e4d5b2011-07-13 15:48:43 -0700661 mCallbacks.onOpenInNewWindow(BrowserBookmarksPage.getUrl(c));
John Reck1b3c66e2011-01-11 13:20:32 -0800662 }
John Reck608baa72010-11-24 10:32:28 -0800663 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800664 }
Nicolas Catania095292f2010-03-15 09:00:14 -0700665
John Reck1b3c66e2011-01-11 13:20:32 -0800666 class OpenAllInTabsTask extends AsyncTask<Void, Void, Cursor> {
667 long mFolderId;
668 public OpenAllInTabsTask(long id) {
669 mFolderId = id;
670 }
671
672 @Override
673 protected Cursor doInBackground(Void... params) {
674 Context c = getActivity();
675 if (c == null) return null;
676 return c.getContentResolver().query(BookmarkUtils.getBookmarksUri(c),
677 BookmarksLoader.PROJECTION, BrowserContract.Bookmarks.PARENT + "=?",
678 new String[] { Long.toString(mFolderId) }, null);
679 }
680
681 @Override
682 protected void onPostExecute(Cursor result) {
John Reckd3e4d5b2011-07-13 15:48:43 -0700683 if (mCallbacks != null && result.getCount() > 0) {
684 String[] urls = new String[result.getCount()];
685 int i = 0;
John Reck1b3c66e2011-01-11 13:20:32 -0800686 while (result.moveToNext()) {
John Reckd3e4d5b2011-07-13 15:48:43 -0700687 urls[i++] = BrowserBookmarksPage.getUrl(result);
John Reck1b3c66e2011-01-11 13:20:32 -0800688 }
John Reckd3e4d5b2011-07-13 15:48:43 -0700689 mCallbacks.onOpenInNewWindow(urls);
John Reck1b3c66e2011-01-11 13:20:32 -0800690 }
691 }
692
693 }
694
John Reck71efc2b2011-05-09 16:54:28 -0700695 private void editBookmark(BrowserBookmarksAdapter adapter, int position) {
Jeff Hamilton64144e42010-08-18 16:31:59 -0500696 Intent intent = new Intent(getActivity(), AddBookmarkPage.class);
John Reck71efc2b2011-05-09 16:54:28 -0700697 Cursor cursor = adapter.getItem(position);
Jeff Hamilton84029622010-08-05 14:29:28 -0500698 Bundle item = new Bundle();
Michael Kolbbef7a752010-08-25 17:11:35 -0700699 item.putString(BrowserContract.Bookmarks.TITLE,
Jeff Hamilton84029622010-08-05 14:29:28 -0500700 cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE));
Michael Kolbbef7a752010-08-25 17:11:35 -0700701 item.putString(BrowserContract.Bookmarks.URL,
Jeff Hamilton84029622010-08-05 14:29:28 -0500702 cursor.getString(BookmarksLoader.COLUMN_INDEX_URL));
703 byte[] data = cursor.getBlob(BookmarksLoader.COLUMN_INDEX_FAVICON);
704 if (data != null) {
Michael Kolbbef7a752010-08-25 17:11:35 -0700705 item.putParcelable(BrowserContract.Bookmarks.FAVICON,
Jeff Hamilton84029622010-08-05 14:29:28 -0500706 BitmapFactory.decodeByteArray(data, 0, data.length));
707 }
John Reckc8490812010-11-22 14:15:36 -0800708 item.putLong(BrowserContract.Bookmarks._ID,
709 cursor.getLong(BookmarksLoader.COLUMN_INDEX_ID));
Leon Scroggins III052ce662010-09-13 14:44:16 -0400710 item.putLong(BrowserContract.Bookmarks.PARENT,
711 cursor.getLong(BookmarksLoader.COLUMN_INDEX_PARENT));
John Reckc8490812010-11-22 14:15:36 -0800712 intent.putExtra(AddBookmarkPage.EXTRA_EDIT_BOOKMARK, item);
713 intent.putExtra(AddBookmarkPage.EXTRA_IS_FOLDER,
714 cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) == 1);
715 startActivity(intent);
Jeff Hamilton84029622010-08-05 14:29:28 -0500716 }
717
John Reck71efc2b2011-05-09 16:54:28 -0700718 private void displayRemoveBookmarkDialog(BrowserBookmarksAdapter adapter,
719 int position) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800720 // Put up a dialog asking if the user really wants to
721 // delete the bookmark
John Reck71efc2b2011-05-09 16:54:28 -0700722 Cursor cursor = adapter.getItem(position);
Leon Scroggins75630672011-01-13 17:56:15 -0500723 long id = cursor.getLong(BookmarksLoader.COLUMN_INDEX_ID);
724 String title = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE);
Jeff Hamilton64144e42010-08-18 16:31:59 -0500725 Context context = getActivity();
Pankaj Garg634bf432015-07-13 09:54:21 -0700726 BookmarkUtils.displayRemoveBookmarkDialog(id, title, context, null,
727 (cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) == 1));
The Android Open Source Project0c908882009-03-03 19:32:16 -0800728 }
729
John Reck71efc2b2011-05-09 16:54:28 -0700730 private String getUrl(BrowserBookmarksAdapter adapter, int position) {
731 return getUrl(adapter.getItem(position));
John Reck608baa72010-11-24 10:32:28 -0800732 }
733
734 /* package */ static String getUrl(Cursor c) {
735 return c.getString(BookmarksLoader.COLUMN_INDEX_URL);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800736 }
Michael Kolb801ecb72010-08-25 12:57:38 -0700737
The Android Open Source Project0c908882009-03-03 19:32:16 -0800738 private void copy(CharSequence text) {
Jeff Hamilton64144e42010-08-18 16:31:59 -0500739 ClipboardManager cm = (ClipboardManager) getActivity().getSystemService(
740 Context.CLIPBOARD_SERVICE);
Dianne Hackbornbf1d10a2011-01-17 12:29:51 -0800741 cm.setPrimaryClip(ClipData.newRawUri(null, Uri.parse(text.toString())));
The Android Open Source Project0c908882009-03-03 19:32:16 -0800742 }
Michael Kolb370a4f32010-10-06 10:45:32 -0700743
John Reckb3417f02011-01-14 11:01:05 -0800744 @Override
John Reckb3417f02011-01-14 11:01:05 -0800745 public void onConfigurationChanged(Configuration newConfig) {
746 super.onConfigurationChanged(newConfig);
747 Resources res = getActivity().getResources();
John Reck71efc2b2011-05-09 16:54:28 -0700748 mGrid.setColumnWidthFromLayout(R.layout.bookmark_thumbnail);
John Reck0ce8a942011-01-14 19:57:09 -0800749 int paddingTop = (int) res.getDimension(R.dimen.combo_paddingTop);
John Reckf3828cd2011-06-14 17:21:55 -0700750 mRoot.setPadding(0, paddingTop, 0, 0);
John Reckb3417f02011-01-14 11:01:05 -0800751 }
752
John Reck608baa72010-11-24 10:32:28 -0800753 /**
754 * BreadCrumb controller callback
755 */
756 @Override
John Reck71efc2b2011-05-09 16:54:28 -0700757 public void onTop(BreadCrumbView view, int level, Object data) {
758 int groupPosition = (Integer) view.getTag(R.id.group_position);
John Reck89f73c12010-12-01 10:10:14 -0800759 Uri uri = (Uri) data;
760 if (uri == null) {
761 // top level
762 uri = BrowserContract.Bookmarks.CONTENT_URI_DEFAULT_FOLDER;
763 }
John Reck71efc2b2011-05-09 16:54:28 -0700764 loadFolder(groupPosition, uri);
John Reckcece1fe2011-09-13 08:47:17 -0700765 if (level <= 1) {
766 view.setVisibility(View.GONE);
767 } else {
768 view.setVisibility(View.VISIBLE);
769 }
John Reck89f73c12010-12-01 10:10:14 -0800770 }
771
772 /**
773 * @param uri
774 */
John Reck71efc2b2011-05-09 16:54:28 -0700775 private void loadFolder(int groupPosition, Uri uri) {
John Reck89f73c12010-12-01 10:10:14 -0800776 LoaderManager manager = getLoaderManager();
John Reck71efc2b2011-05-09 16:54:28 -0700777 // This assumes groups are ordered the same as loaders
778 BookmarksLoader loader = (BookmarksLoader) ((Loader<?>)
779 manager.getLoader(LOADER_BOOKMARKS + groupPosition));
John Reck89f73c12010-12-01 10:10:14 -0800780 loader.setUri(uri);
781 loader.forceLoad();
John Reck608baa72010-11-24 10:32:28 -0800782 }
783
John Reck608baa72010-11-24 10:32:28 -0800784 public void setCallbackListener(BookmarksPageCallbacks callbackListener) {
785 mCallbacks = callbackListener;
786 }
787
788 public void setEnableContextMenu(boolean enable) {
789 mEnableContextMenu = enable;
790 if (mGrid != null) {
791 if (mEnableContextMenu) {
792 registerForContextMenu(mGrid);
793 } else {
794 unregisterForContextMenu(mGrid);
795 mGrid.setLongClickable(false);
796 }
797 }
John Reck608baa72010-11-24 10:32:28 -0800798 }
John Reckc8490812010-11-22 14:15:36 -0800799
800 private static class LookupBookmarkCount extends AsyncTask<Long, Void, Integer> {
801 Context mContext;
802 BookmarkItem mHeader;
803
804 public LookupBookmarkCount(Context context, BookmarkItem header) {
Ben Murdoch914c5592011-08-01 13:58:47 +0100805 mContext = context.getApplicationContext();
John Reckc8490812010-11-22 14:15:36 -0800806 mHeader = header;
807 }
808
809 @Override
810 protected Integer doInBackground(Long... params) {
811 if (params.length != 1) {
812 throw new IllegalArgumentException("Missing folder id!");
813 }
814 Uri uri = BookmarkUtils.getBookmarksUri(mContext);
Axesh R. Ajmera632e5a02014-11-13 09:52:46 -0800815 Cursor c = null;
816 try {
817 c = mContext.getContentResolver().query(uri,
818 null, BrowserContract.Bookmarks.PARENT + "=?",
819 new String[] {params[0].toString()}, null);
820 return c.getCount();
821 } finally {
822 if (c != null) {
823 c.close();
824 }
825 }
John Reckc8490812010-11-22 14:15:36 -0800826 }
827
828 @Override
829 protected void onPostExecute(Integer result) {
830 if (result > 0) {
831 mHeader.setUrl(mContext.getString(R.string.contextheader_folder_bookmarkcount,
832 result));
833 } else if (result == 0) {
834 mHeader.setUrl(mContext.getString(R.string.contextheader_folder_empty));
835 }
836 }
837 }
John Reck89f73c12010-12-01 10:10:14 -0800838
John Reck71efc2b2011-05-09 16:54:28 -0700839 static class AccountsLoader extends CursorLoader {
John Reck89f73c12010-12-01 10:10:14 -0800840
John Reck71efc2b2011-05-09 16:54:28 -0700841 static String[] ACCOUNTS_PROJECTION = new String[] {
842 Accounts.ACCOUNT_NAME,
843 Accounts.ACCOUNT_TYPE
844 };
John Reck89f73c12010-12-01 10:10:14 -0800845
John Reck71efc2b2011-05-09 16:54:28 -0700846 public AccountsLoader(Context context) {
John Reck1e9815d2011-08-08 17:45:05 -0700847 super(context, Accounts.CONTENT_URI
848 .buildUpon()
849 .appendQueryParameter(BrowserProvider2.PARAM_ALLOW_EMPTY_ACCOUNTS, "false")
850 .build(),
851 ACCOUNTS_PROJECTION, null, null, null);
John Reck89f73c12010-12-01 10:10:14 -0800852 }
John Reck522a4382011-01-26 13:23:47 -0800853
John Reck522a4382011-01-26 13:23:47 -0800854 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800855}