1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)package org.chromium.chrome.browser; 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)import android.annotation.SuppressLint; 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.app.SearchManager; 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.content.ContentProvider; 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.content.ContentUris; 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.content.ContentValues; 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.content.Context; 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.content.SharedPreferences; 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.content.UriMatcher; 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.database.Cursor; 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.database.MatrixCursor; 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.net.Uri; 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.os.Binder; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.os.Build; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.os.Bundle; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.os.Parcel; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.os.Parcelable; 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)import android.os.UserHandle; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.preference.PreferenceManager; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.provider.BaseColumns; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.provider.Browser; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.provider.Browser.BookmarkColumns; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.provider.Browser.SearchColumns; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.text.TextUtils; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.util.Log; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.chromium.base.CalledByNative; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.chromium.base.CalledByNativeUnchecked; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.chromium.base.ThreadUtils; 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport org.chromium.base.VisibleForTesting; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.chromium.chrome.browser.database.SQLiteCursor; 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import org.chromium.sync.notifier.SyncStatusHelper; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.util.ArrayList; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.util.Arrays; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.util.HashMap; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.util.List; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.util.Vector; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.util.concurrent.atomic.AtomicBoolean; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * This class provides access to user data stored in Chrome, such as bookmarks, most visited pages, 48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * etc. It is used to support android.provider.Browser. 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public class ChromeBrowserProvider extends ContentProvider { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final String TAG = "ChromeBrowserProvider"; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The permission required for using the bookmark folders API. Android build system does 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // not generate Manifest.java for java libraries, hence use the permission name string. When 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // making changes to this permission, also update the permission in AndroidManifest.xml. 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private static final String PERMISSION_READ_WRITE_BOOKMARKS = "READ_WRITE_BOOKMARK_FOLDERS"; 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Defines the API methods that the Client can call by name. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static final String CLIENT_API_BOOKMARK_NODE_EXISTS = "BOOKMARK_NODE_EXISTS"; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static final String CLIENT_API_CREATE_BOOKMARKS_FOLDER_ONCE = "CREATE_BOOKMARKS_FOLDER_ONCE"; 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) static final String CLIENT_API_GET_EDITABLE_BOOKMARK_FOLDER_HIERARCHY = 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "GET_EDITABLE_BOOKMARK_FOLDER_HIERARCHY"; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static final String CLIENT_API_GET_BOOKMARK_NODE = "GET_BOOKMARK_NODE"; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static final String CLIENT_API_GET_DEFAULT_BOOKMARK_FOLDER = "GET_DEFAULT_BOOKMARK_FOLDER"; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static final String CLIENT_API_GET_MOBILE_BOOKMARKS_FOLDER_ID = 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "GET_MOBILE_BOOKMARKS_FOLDER_ID"; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static final String CLIENT_API_IS_BOOKMARK_IN_MOBILE_BOOKMARKS_BRANCH = 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "IS_BOOKMARK_IN_MOBILE_BOOKMARKS_BRANCH"; 69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) static final String CLIENT_API_DELETE_ALL_USER_BOOKMARKS = "DELETE_ALL_USER_BOOKMARKS"; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static final String CLIENT_API_RESULT_KEY = "result"; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Defines Chrome's API authority, so it can be run and tested 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // independently. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final String API_AUTHORITY_SUFFIX = ".browser"; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final String BROWSER_CONTRACT_API_AUTHORITY = 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "com.google.android.apps.chrome.browser-contract"; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // These values are taken from android.provider.BrowserContract.java since 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that class is hidden from the SDK. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final String BROWSER_CONTRACT_AUTHORITY = "com.android.browser"; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final String BROWSER_CONTRACT_HISTORY_CONTENT_TYPE = 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "vnd.android.cursor.dir/browser-history"; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final String BROWSER_CONTRACT_HISTORY_CONTENT_ITEM_TYPE = 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "vnd.android.cursor.item/browser-history"; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This Authority is for internal interface. It's concatenated with 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Context.getPackageName() so that we can install different channels 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SxS and have different authorities. 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final String AUTHORITY_SUFFIX = ".ChromeBrowserProvider"; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final String BOOKMARKS_PATH = "bookmarks"; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final String SEARCHES_PATH = "searches"; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final String HISTORY_PATH = "history"; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final String COMBINED_PATH = "combined"; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final String BOOKMARK_FOLDER_PATH = "hierarchy"; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public static final Uri BROWSER_CONTRACTS_BOOKMAKRS_API_URI = buildContentUri( 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BROWSER_CONTRACT_API_AUTHORITY, BOOKMARKS_PATH); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public static final Uri BROWSER_CONTRACTS_SEARCHES_API_URI = buildContentUri( 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BROWSER_CONTRACT_API_AUTHORITY, SEARCHES_PATH); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public static final Uri BROWSER_CONTRACTS_HISTORY_API_URI = buildContentUri( 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BROWSER_CONTRACT_API_AUTHORITY, HISTORY_PATH); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public static final Uri BROWSER_CONTRACTS_COMBINED_API_URI = buildContentUri( 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BROWSER_CONTRACT_API_AUTHORITY, COMBINED_PATH); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** The parameter used to specify a bookmark parent ID in ContentValues. */ 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public static final String BOOKMARK_PARENT_ID_PARAM = "parentId"; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** The parameter used to specify whether this is a bookmark folder. */ 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public static final String BOOKMARK_IS_FOLDER_PARAM = "isFolder"; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) /** 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * Invalid ID value for the Android ContentProvider API calls. 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * The value 0 is intentional: if the ID represents a bookmark node then it's the root node 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * and not accessible. Otherwise it represents a SQLite row id, so 0 is also invalid. 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) */ 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public static final long INVALID_CONTENT_PROVIDER_ID = 0; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ID used to indicate an invalid id for bookmark nodes. 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Client API queries should use ChromeBrowserProviderClient.INVALID_BOOKMARK_ID. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static final long INVALID_BOOKMARK_ID = -1; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final String LAST_MODIFIED_BOOKMARK_FOLDER_ID_KEY = "last_bookmark_folder_id"; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final int URI_MATCH_BOOKMARKS = 0; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final int URI_MATCH_BOOKMARKS_ID = 1; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final int URL_MATCH_API_BOOKMARK = 2; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final int URL_MATCH_API_BOOKMARK_ID = 3; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final int URL_MATCH_API_SEARCHES = 4; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final int URL_MATCH_API_SEARCHES_ID = 5; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final int URL_MATCH_API_HISTORY_CONTENT = 6; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final int URL_MATCH_API_HISTORY_CONTENT_ID = 7; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final int URL_MATCH_API_BOOKMARK_CONTENT = 8; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final int URL_MATCH_API_BOOKMARK_CONTENT_ID = 9; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final int URL_MATCH_BOOKMARK_SUGGESTIONS_ID = 10; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final int URL_MATCH_BOOKMARK_HISTORY_SUGGESTIONS_ID = 11; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO : Using Android.provider.Browser.HISTORY_PROJECTION once THUMBNAIL, 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TOUCH_ICON, and USER_ENTERED fields are supported. 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final String[] BOOKMARK_DEFAULT_PROJECTION = new String[] { 145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BookmarkColumns._ID, BookmarkColumns.URL, BookmarkColumns.VISITS, 146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BookmarkColumns.DATE, BookmarkColumns.BOOKMARK, BookmarkColumns.TITLE, 147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BookmarkColumns.FAVICON, BookmarkColumns.CREATED 148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) }; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final String[] SUGGEST_PROJECTION = new String[] { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkColumns._ID, 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkColumns.TITLE, 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkColumns.URL, 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkColumns.DATE, 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkColumns.BOOKMARK 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private final Object mInitializeUriMatcherLock = new Object(); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private final Object mLoadNativeLock = new Object(); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private UriMatcher mUriMatcher; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private long mLastModifiedBookmarkFolderId = INVALID_BOOKMARK_ID; 162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private long mNativeChromeBrowserProvider; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private BookmarkNode mMobileBookmarksFolder; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) /** 16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * Records whether we've received a call to one of the public ContentProvider APIs. 16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) */ 16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) protected boolean mContentProviderApiCalled; 16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private void ensureUriMatcherInitialized() { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) synchronized (mInitializeUriMatcherLock) { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mUriMatcher != null) return; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The internal URIs 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String authority = getContext().getPackageName() + AUTHORITY_SUFFIX; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(authority, BOOKMARKS_PATH, URI_MATCH_BOOKMARKS); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(authority, BOOKMARKS_PATH + "/#", URI_MATCH_BOOKMARKS_ID); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The internal authority for public APIs 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String apiAuthority = getContext().getPackageName() + API_AUTHORITY_SUFFIX; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(apiAuthority, BOOKMARKS_PATH, URL_MATCH_API_BOOKMARK); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(apiAuthority, BOOKMARKS_PATH + "/#", URL_MATCH_API_BOOKMARK_ID); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(apiAuthority, SEARCHES_PATH, URL_MATCH_API_SEARCHES); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(apiAuthority, SEARCHES_PATH + "/#", URL_MATCH_API_SEARCHES_ID); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(apiAuthority, HISTORY_PATH, URL_MATCH_API_HISTORY_CONTENT); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(apiAuthority, HISTORY_PATH + "/#", URL_MATCH_API_HISTORY_CONTENT_ID); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(apiAuthority, COMBINED_PATH, URL_MATCH_API_BOOKMARK); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(apiAuthority, COMBINED_PATH + "/#", URL_MATCH_API_BOOKMARK_ID); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The internal authority for BrowserContracts 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(BROWSER_CONTRACT_API_AUTHORITY, HISTORY_PATH, 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URL_MATCH_API_HISTORY_CONTENT); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(BROWSER_CONTRACT_API_AUTHORITY, HISTORY_PATH + "/#", 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URL_MATCH_API_HISTORY_CONTENT_ID); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(BROWSER_CONTRACT_API_AUTHORITY, COMBINED_PATH, 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URL_MATCH_API_BOOKMARK); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(BROWSER_CONTRACT_API_AUTHORITY, COMBINED_PATH + "/#", 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URL_MATCH_API_BOOKMARK_ID); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(BROWSER_CONTRACT_API_AUTHORITY, SEARCHES_PATH, 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URL_MATCH_API_SEARCHES); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(BROWSER_CONTRACT_API_AUTHORITY, SEARCHES_PATH + "/#", 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URL_MATCH_API_SEARCHES_ID); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(BROWSER_CONTRACT_API_AUTHORITY, BOOKMARKS_PATH, 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URL_MATCH_API_BOOKMARK_CONTENT); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(BROWSER_CONTRACT_API_AUTHORITY, BOOKMARKS_PATH + "/#", 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URL_MATCH_API_BOOKMARK_CONTENT_ID); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Added the Android Framework URIs, so the provider can easily switched 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by adding 'browser' and 'com.android.browser' in manifest. 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The Android's BrowserContract 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(BROWSER_CONTRACT_AUTHORITY, HISTORY_PATH, 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URL_MATCH_API_HISTORY_CONTENT); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(BROWSER_CONTRACT_AUTHORITY, HISTORY_PATH + "/#", 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URL_MATCH_API_HISTORY_CONTENT_ID); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(BROWSER_CONTRACT_AUTHORITY, "combined", URL_MATCH_API_BOOKMARK); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(BROWSER_CONTRACT_AUTHORITY, "combined/#", URL_MATCH_API_BOOKMARK_ID); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(BROWSER_CONTRACT_AUTHORITY, SEARCHES_PATH, URL_MATCH_API_SEARCHES); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(BROWSER_CONTRACT_AUTHORITY, SEARCHES_PATH + "/#", 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URL_MATCH_API_SEARCHES_ID); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(BROWSER_CONTRACT_AUTHORITY, BOOKMARKS_PATH, 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URL_MATCH_API_BOOKMARK_CONTENT); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(BROWSER_CONTRACT_AUTHORITY, BOOKMARKS_PATH + "/#", 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URL_MATCH_API_BOOKMARK_CONTENT_ID); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For supporting android.provider.browser.BookmarkColumns and 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SearchColumns 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI("browser", BOOKMARKS_PATH, URL_MATCH_API_BOOKMARK); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI("browser", BOOKMARKS_PATH + "/#", URL_MATCH_API_BOOKMARK_ID); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI("browser", SEARCHES_PATH, URL_MATCH_API_SEARCHES); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI("browser", SEARCHES_PATH + "/#", URL_MATCH_API_SEARCHES_ID); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(apiAuthority, 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOKMARKS_PATH + "/" + SearchManager.SUGGEST_URI_PATH_QUERY, 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URL_MATCH_BOOKMARK_SUGGESTIONS_ID); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUriMatcher.addURI(apiAuthority, 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SearchManager.SUGGEST_URI_PATH_QUERY, 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URL_MATCH_BOOKMARK_HISTORY_SUGGESTIONS_ID); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @Override 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public boolean onCreate() { 240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Pre-load shared preferences object, this happens on a separate thread 241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PreferenceManager.getDefaultSharedPreferences(getContext()); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /** 246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Lazily fetches the last modified bookmark folder id. 247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private long getLastModifiedBookmarkFolderId() { 249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (mLastModifiedBookmarkFolderId == INVALID_BOOKMARK_ID) { 250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SharedPreferences sharedPreferences = 251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PreferenceManager.getDefaultSharedPreferences(getContext()); 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mLastModifiedBookmarkFolderId = sharedPreferences.getLong( 253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LAST_MODIFIED_BOOKMARK_FOLDER_ID_KEY, INVALID_BOOKMARK_ID); 254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return mLastModifiedBookmarkFolderId; 256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private String buildSuggestWhere(String selection, int argc) { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringBuilder sb = new StringBuilder(selection); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < argc - 1; i++) { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sb.append(" OR "); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sb.append(selection); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sb.toString(); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private String getReadWritePermissionNameForBookmarkFolders() { 268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return getContext().getApplicationContext().getPackageName() + ".permission." 269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) + PERMISSION_READ_WRITE_BOOKMARKS; 270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private Cursor getBookmarkHistorySuggestions(String selection, String[] selectionArgs, 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String sortOrder, boolean excludeHistory) { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) boolean matchTitles = false; 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Vector<String> args = new Vector<String>(); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String like = selectionArgs[0] + "%"; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (selectionArgs[0].startsWith("http") || selectionArgs[0].startsWith("file")) { 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.add(like); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Match against common URL prefixes. 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.add("http://" + like); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.add("https://" + like); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.add("http://www." + like); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.add("https://www." + like); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.add("file://" + like); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) matchTitles = true; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringBuilder urlWhere = new StringBuilder("("); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) urlWhere.append(buildSuggestWhere(selection, args.size())); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (matchTitles) { 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.add(like); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) urlWhere.append(" OR title LIKE ?"); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) urlWhere.append(")"); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (excludeHistory) { 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) urlWhere.append(" AND bookmark=?"); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.add("1"); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selectionArgs = args.toArray(selectionArgs); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Cursor cursor = queryBookmarkFromAPI(SUGGEST_PROJECTION, urlWhere.toString(), 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selectionArgs, sortOrder); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new ChromeBrowserProviderSuggestionsCursor(cursor); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) /** 309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * @see android.content.ContentUris#parseId(Uri) 310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * @return The id from a content URI or -1 if the URI has no id or is malformed. 311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) */ 312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private static long getContentUriId(Uri uri) { 313a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) try { 314a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return ContentUris.parseId(uri); 315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } catch (UnsupportedOperationException e) { 316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return -1; 317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } catch (NumberFormatException e) { 318a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return -1; 319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 320a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 321a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @Override 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String sortOrder) { 32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!canHandleContentProviderApiCall()) return null; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for invalid id values if provided. 328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) long bookmarkId = getContentUriId(uri); 329a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (bookmarkId == INVALID_CONTENT_PROVIDER_ID) return null; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int match = mUriMatcher.match(uri); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Cursor cursor = null; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (match) { 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_BOOKMARK_SUGGESTIONS_ID: 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cursor = getBookmarkHistorySuggestions(selection, selectionArgs, sortOrder, true); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_BOOKMARK_HISTORY_SUGGESTIONS_ID: 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cursor = getBookmarkHistorySuggestions(selection, selectionArgs, sortOrder, false); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_BOOKMARK: 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cursor = queryBookmarkFromAPI(projection, selection, selectionArgs, sortOrder); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_BOOKMARK_ID: 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cursor = queryBookmarkFromAPI(projection, buildWhereClause(bookmarkId, selection), 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selectionArgs, sortOrder); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_SEARCHES: 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cursor = querySearchTermFromAPI(projection, selection, selectionArgs, sortOrder); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_SEARCHES_ID: 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cursor = querySearchTermFromAPI(projection, buildWhereClause(bookmarkId, selection), 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selectionArgs, sortOrder); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_HISTORY_CONTENT: 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cursor = queryBookmarkFromAPI(projection, buildHistoryWhereClause(selection), 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selectionArgs, sortOrder); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_HISTORY_CONTENT_ID: 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cursor = queryBookmarkFromAPI(projection, 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buildHistoryWhereClause(bookmarkId, selection), selectionArgs, sortOrder); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_BOOKMARK_CONTENT: 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cursor = queryBookmarkFromAPI(projection, buildBookmarkWhereClause(selection), 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selectionArgs, sortOrder); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_BOOKMARK_CONTENT_ID: 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cursor = queryBookmarkFromAPI(projection, 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buildBookmarkWhereClause(bookmarkId, selection), selectionArgs, sortOrder); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw new IllegalArgumentException(TAG + ": query - unknown URL uri = " + uri); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cursor == null) { 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cursor = new MatrixCursor(new String[] { }); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cursor.setNotificationUri(getContext().getContentResolver(), uri); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cursor; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @Override 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public Uri insert(Uri uri, ContentValues values) { 38290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!canHandleContentProviderApiCall()) return null; 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int match = mUriMatcher.match(uri); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Uri res = null; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long id; 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (match) { 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URI_MATCH_BOOKMARKS: 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) id = addBookmark(values); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (id == INVALID_BOOKMARK_ID) return null; 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_BOOKMARK_CONTENT: 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) values.put(BookmarkColumns.BOOKMARK, 1); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) //$FALL-THROUGH$ 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_BOOKMARK: 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_HISTORY_CONTENT: 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) id = addBookmarkFromAPI(values); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (id == INVALID_CONTENT_PROVIDER_ID) return null; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_SEARCHES: 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) id = addSearchTermFromAPI(values); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (id == INVALID_CONTENT_PROVIDER_ID) return null; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw new IllegalArgumentException(TAG + ": insert - unknown URL " + uri); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res = ContentUris.withAppendedId(uri, id); 409a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) notifyChange(res); 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return res; 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @Override 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public int delete(Uri uri, String selection, String[] selectionArgs) { 41590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!canHandleContentProviderApiCall()) return 0; 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for invalid id values if provided. 418a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) long bookmarkId = getContentUriId(uri); 419a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (bookmarkId == INVALID_CONTENT_PROVIDER_ID) return 0; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int match = mUriMatcher.match(uri); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (match) { 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URI_MATCH_BOOKMARKS_ID : 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = nativeRemoveBookmark(mNativeChromeBrowserProvider, bookmarkId); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_BOOKMARK_ID: 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = removeBookmarkFromAPI( 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buildWhereClause(bookmarkId, selection), selectionArgs); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_BOOKMARK: 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = removeBookmarkFromAPI(selection, selectionArgs); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_SEARCHES_ID: 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = removeSearchFromAPI(buildWhereClause(bookmarkId, selection), 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selectionArgs); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_SEARCHES: 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = removeSearchFromAPI(selection, selectionArgs); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_HISTORY_CONTENT: 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = removeHistoryFromAPI(selection, selectionArgs); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_HISTORY_CONTENT_ID: 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = removeHistoryFromAPI(buildWhereClause(bookmarkId, selection), 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selectionArgs); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_BOOKMARK_CONTENT: 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = removeBookmarkFromAPI(buildBookmarkWhereClause(selection), selectionArgs); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_BOOKMARK_CONTENT_ID: 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = removeBookmarkFromAPI(buildBookmarkWhereClause(bookmarkId, selection), 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selectionArgs); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw new IllegalArgumentException(TAG + ": delete - unknown URL " + uri); 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 458a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (result != 0) notifyChange(uri); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @Override 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 46490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!canHandleContentProviderApiCall()) return 0; 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for invalid id values if provided. 467a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) long bookmarkId = getContentUriId(uri); 468a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (bookmarkId == INVALID_CONTENT_PROVIDER_ID) return 0; 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int match = mUriMatcher.match(uri); 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result; 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (match) { 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URI_MATCH_BOOKMARKS_ID: 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String url = null; 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (values.containsKey(Browser.BookmarkColumns.URL)) { 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url = values.getAsString(Browser.BookmarkColumns.URL); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String title = values.getAsString(Browser.BookmarkColumns.TITLE); 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long parentId = INVALID_BOOKMARK_ID; 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (values.containsKey(BOOKMARK_PARENT_ID_PARAM)) { 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parentId = values.getAsLong(BOOKMARK_PARENT_ID_PARAM); 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = nativeUpdateBookmark(mNativeChromeBrowserProvider, bookmarkId, url, title, 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parentId); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) updateLastModifiedBookmarkFolder(parentId); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_BOOKMARK_ID: 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = updateBookmarkFromAPI(values, buildWhereClause(bookmarkId, selection), 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selectionArgs); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_BOOKMARK: 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = updateBookmarkFromAPI(values, selection, selectionArgs); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_SEARCHES_ID: 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = updateSearchTermFromAPI(values, buildWhereClause(bookmarkId, selection), 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selectionArgs); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_SEARCHES: 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = updateSearchTermFromAPI(values, selection, selectionArgs); 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_HISTORY_CONTENT: 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = updateBookmarkFromAPI(values, buildHistoryWhereClause(selection), 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selectionArgs); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_HISTORY_CONTENT_ID: 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = updateBookmarkFromAPI(values, 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buildHistoryWhereClause(bookmarkId, selection), selectionArgs); 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_BOOKMARK_CONTENT: 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = updateBookmarkFromAPI(values, buildBookmarkWhereClause(selection), 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selectionArgs); 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_BOOKMARK_CONTENT_ID: 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = updateBookmarkFromAPI(values, 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buildBookmarkWhereClause(bookmarkId, selection), selectionArgs); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw new IllegalArgumentException(TAG + ": update - unknown URL " + uri); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 520a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (result != 0) notifyChange(uri); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @Override 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public String getType(Uri uri) { 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ensureUriMatcherInitialized(); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int match = mUriMatcher.match(uri); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (match) { 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URI_MATCH_BOOKMARKS: 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_BOOKMARK: 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "vnd.android.cursor.dir/bookmark"; 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URI_MATCH_BOOKMARKS_ID: 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_BOOKMARK_ID: 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "vnd.android.cursor.item/bookmark"; 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_SEARCHES: 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "vnd.android.cursor.dir/searches"; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_SEARCHES_ID: 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "vnd.android.cursor.item/searches"; 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_HISTORY_CONTENT: 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return BROWSER_CONTRACT_HISTORY_CONTENT_TYPE; 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case URL_MATCH_API_HISTORY_CONTENT_ID: 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return BROWSER_CONTRACT_HISTORY_CONTENT_ITEM_TYPE; 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw new IllegalArgumentException(TAG + ": getType - unknown URL " + uri); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private long addBookmark(ContentValues values) { 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String url = values.getAsString(Browser.BookmarkColumns.URL); 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String title = values.getAsString(Browser.BookmarkColumns.TITLE); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) boolean isFolder = false; 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (values.containsKey(BOOKMARK_IS_FOLDER_PARAM)) { 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) isFolder = values.getAsBoolean(BOOKMARK_IS_FOLDER_PARAM); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long parentId = INVALID_BOOKMARK_ID; 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (values.containsKey(BOOKMARK_PARENT_ID_PARAM)) { 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parentId = values.getAsLong(BOOKMARK_PARENT_ID_PARAM); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long id = nativeAddBookmark(mNativeChromeBrowserProvider, url, title, isFolder, parentId); 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (id == INVALID_BOOKMARK_ID) return id; 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isFolder) { 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) updateLastModifiedBookmarkFolder(id); 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) updateLastModifiedBookmarkFolder(parentId); 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return id; 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private void updateLastModifiedBookmarkFolder(long id) { 571c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (getLastModifiedBookmarkFolderId() == id) return; 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mLastModifiedBookmarkFolderId = id; 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SharedPreferences sharedPreferences = 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PreferenceManager.getDefaultSharedPreferences(getContext()); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sharedPreferences.edit() 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .putLong(LAST_MODIFIED_BOOKMARK_FOLDER_ID_KEY, mLastModifiedBookmarkFolderId) 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .apply(); 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public static String getApiAuthority(Context context) { 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return context.getPackageName() + API_AUTHORITY_SUFFIX; 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public static String getInternalAuthority(Context context) { 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return context.getPackageName() + AUTHORITY_SUFFIX; 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public static Uri getBookmarksUri(Context context) { 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buildContentUri(getInternalAuthority(context), BOOKMARKS_PATH); 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public static Uri getBookmarkFolderUri(Context context) { 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buildContentUri(getInternalAuthority(context), BOOKMARK_FOLDER_PATH); 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public static Uri getBookmarksApiUri(Context context) { 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buildContentUri(getApiAuthority(context), BOOKMARKS_PATH); 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public static Uri getSearchesApiUri(Context context) { 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buildContentUri(getApiAuthority(context), SEARCHES_PATH); 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private boolean bookmarkNodeExists(long nodeId) { 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (nodeId < 0) return false; 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return nativeBookmarkNodeExists(mNativeChromeBrowserProvider, nodeId); 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private long createBookmarksFolderOnce(String title, long parentId) { 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return nativeCreateBookmarksFolderOnce(mNativeChromeBrowserProvider, title, parentId); 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 614f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private BookmarkNode getEditableBookmarkFolderHierarchy() { 615f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return nativeGetEditableBookmarkFolders(mNativeChromeBrowserProvider); 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected BookmarkNode getBookmarkNode(long nodeId, boolean getParent, boolean getChildren, 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) boolean getFavicons, boolean getThumbnails) { 620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Don't allow going up the hierarchy if sync is disabled and the requested node 621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // is the Mobile Bookmarks folder. 622c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (getParent && nodeId == getMobileBookmarksFolderId() 623c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) && !SyncStatusHelper.get(getContext()).isSyncEnabled()) { 624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) getParent = false; 625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode node = nativeGetBookmarkNode(mNativeChromeBrowserProvider, nodeId, getParent, 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getChildren); 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!getFavicons && !getThumbnails) return node; 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Favicons and thumbnails need to be populated separately as they are provided 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // asynchronously by Chromium services other than the bookmark model. 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (node.parent() != null) populateNodeImages(node.parent(), getFavicons, getThumbnails); 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (BookmarkNode child : node.children()) { 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) populateNodeImages(child, getFavicons, getThumbnails); 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return node; 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private BookmarkNode getDefaultBookmarkFolder() { 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try to access the bookmark folder last modified by us. If it doesn't exist anymore 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // then use the synced node (Mobile Bookmarks). 644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) BookmarkNode lastModified = getBookmarkNode(getLastModifiedBookmarkFolderId(), false, false, 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false, false); 6465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (lastModified == null || lastModified.isUrl()) { 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lastModified = getMobileBookmarksFolder(); 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mLastModifiedBookmarkFolderId = lastModified != null ? lastModified.id() : 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INVALID_BOOKMARK_ID; 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return lastModified; 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private void populateNodeImages(BookmarkNode node, boolean favicon, boolean thumbnail) { 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (node == null || node.type() != Type.URL) return; 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (favicon) { 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node.setFavicon(nativeGetFaviconOrTouchIcon(mNativeChromeBrowserProvider, node.url())); 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (thumbnail) { 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node.setThumbnail(nativeGetThumbnail(mNativeChromeBrowserProvider, node.url())); 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private BookmarkNode getMobileBookmarksFolder() { 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mMobileBookmarksFolder == null) { 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mMobileBookmarksFolder = nativeGetMobileBookmarksFolder(mNativeChromeBrowserProvider); 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mMobileBookmarksFolder; 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected long getMobileBookmarksFolderId() { 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode mobileBookmarks = getMobileBookmarksFolder(); 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mobileBookmarks != null ? mobileBookmarks.id() : INVALID_BOOKMARK_ID; 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private boolean isBookmarkInMobileBookmarksBranch(long nodeId) { 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (nodeId <= 0) return false; 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return nativeIsBookmarkInMobileBookmarksBranch(mNativeChromeBrowserProvider, nodeId); 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static String argKey(int i) { 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "arg" + i; 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @Override 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public Bundle call(String method, String arg, Bundle extras) { 6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(shashishekhar): Refactor this code into a separate class. 6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Caller must have the READ_WRITE_BOOKMARK_FOLDERS permission. 691c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) getContext().enforcePermission(getReadWritePermissionNameForBookmarkFolders(), 692c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Binder.getCallingPid(), Binder.getCallingUid(), TAG); 69390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!canHandleContentProviderApiCall()) return null; 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (method == null || extras == null) return null; 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Bundle result = new Bundle(); 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CLIENT_API_BOOKMARK_NODE_EXISTS.equals(method)) { 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.putBoolean(CLIENT_API_RESULT_KEY, 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmarkNodeExists(extras.getLong(argKey(0)))); 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (CLIENT_API_CREATE_BOOKMARKS_FOLDER_ONCE.equals(method)) { 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.putLong(CLIENT_API_RESULT_KEY, 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) createBookmarksFolderOnce(extras.getString(argKey(0)), 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extras.getLong(argKey(1)))); 704f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else if (CLIENT_API_GET_EDITABLE_BOOKMARK_FOLDER_HIERARCHY.equals(method)) { 705f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.putParcelable(CLIENT_API_RESULT_KEY, getEditableBookmarkFolderHierarchy()); 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (CLIENT_API_GET_BOOKMARK_NODE.equals(method)) { 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.putParcelable(CLIENT_API_RESULT_KEY, 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getBookmarkNode(extras.getLong(argKey(0)), 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extras.getBoolean(argKey(1)), 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extras.getBoolean(argKey(2)), 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extras.getBoolean(argKey(3)), 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extras.getBoolean(argKey(4)))); 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (CLIENT_API_GET_DEFAULT_BOOKMARK_FOLDER.equals(method)) { 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.putParcelable(CLIENT_API_RESULT_KEY, getDefaultBookmarkFolder()); 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (method.equals(CLIENT_API_GET_MOBILE_BOOKMARKS_FOLDER_ID)) { 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.putLong(CLIENT_API_RESULT_KEY, getMobileBookmarksFolderId()); 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (CLIENT_API_IS_BOOKMARK_IN_MOBILE_BOOKMARKS_BRANCH.equals(method)) { 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.putBoolean(CLIENT_API_RESULT_KEY, 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) isBookmarkInMobileBookmarksBranch(extras.getLong(argKey(0)))); 720f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else if (CLIENT_API_DELETE_ALL_USER_BOOKMARKS.equals(method)) { 721f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) nativeRemoveAllUserBookmarks(mNativeChromeBrowserProvider); 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Log.w(TAG, "Received invalid method " + method); 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return null; 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 73190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * Checks whether Chrome is sufficiently initialized to handle a call to the 73290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * ChromeBrowserProvider. 73390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) */ 73490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private boolean canHandleContentProviderApiCall() { 73590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) mContentProviderApiCalled = true; 73690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 73790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (isInUiThread()) return false; 73890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!ensureNativeChromeLoaded()) return false; 73990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return true; 74090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 74190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 74290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) /** 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The type of a BookmarkNode. 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public enum Type { 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URL, 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOLDER, 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOKMARK_BAR, 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OTHER_NODE, 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MOBILE 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Simple Data Object representing the chrome bookmark node. 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public static class BookmarkNode implements Parcelable { 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private final long mId; 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private final String mName; 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private final String mUrl; 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private final Type mType; 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private final BookmarkNode mParent; 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private final List<BookmarkNode> mChildren = new ArrayList<BookmarkNode>(); 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Favicon and thumbnail optionally set in a 2-step procedure. 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private byte[] mFavicon; 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private byte[] mThumbnail; 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Used to pass structured data back from the native code. */ 7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @VisibleForTesting 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public BookmarkNode(long id, Type type, String name, String url, BookmarkNode parent) { 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mId = id; 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mName = name; 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mUrl = url; 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mType = type; 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mParent = parent; 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return The id of this bookmark entry. 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public long id() { 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mId; 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return The name of this bookmark entry. 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public String name() { 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mName; 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return The URL of this bookmark entry. 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public String url() { 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mUrl; 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return The type of this bookmark entry. 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public Type type() { 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mType; 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return The bookmark favicon, if any. 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public byte[] favicon() { 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mFavicon; 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return The bookmark thumbnail, if any. 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public byte[] thumbnail() { 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mThumbnail; 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return The parent folder of this bookmark entry. 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public BookmarkNode parent() { 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mParent; 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Adds a child to this node. 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * <p> 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Used solely by the native code. 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @VisibleForTesting 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @CalledByNativeUnchecked("BookmarkNode") 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public void addChild(BookmarkNode child) { 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mChildren.add(child); 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return The child bookmark nodes of this node. 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public List<BookmarkNode> children() { 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mChildren; 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return Whether this node represents a bookmarked URL or not. 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public boolean isUrl() { 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mUrl != null; 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return true if the two individual nodes contain the same information. 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The existence of parent and children nodes is checked, but their contents are not. 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public boolean equalContents(BookmarkNode node) { 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return node != null && 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mId == node.mId && 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !(mName == null ^ node.mName == null) && 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (mName == null || mName.equals(node.mName)) && 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !(mUrl == null ^ node.mUrl == null) && 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (mUrl == null || mUrl.equals(node.mUrl)) && 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mType == node.mType && 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) byteArrayEqual(mFavicon, node.mFavicon) && 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) byteArrayEqual(mThumbnail, node.mThumbnail) && 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !(mParent == null ^ node.mParent == null) && 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) children().size() == node.children().size(); 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static boolean byteArrayEqual(byte[] byte1, byte[] byte2) { 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (byte1 == null && byte2 != null) return byte2.length == 0; 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (byte2 == null && byte1 != null) return byte1.length == 0; 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Arrays.equals(byte1, byte2); 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @CalledByNative("BookmarkNode") 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static BookmarkNode create( 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long id, int type, String name, String url, BookmarkNode parent) { 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new BookmarkNode(id, Type.values()[type], name, url, parent); 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @VisibleForTesting 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public void setFavicon(byte[] favicon) { 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mFavicon = favicon; 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @VisibleForTesting 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public void setThumbnail(byte[] thumbnail) { 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mThumbnail = thumbnail; 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @Override 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public int describeContents() { 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @Override 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public void writeToParcel(Parcel dest, int flags) { 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Write the current node id. 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest.writeLong(mId); 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Serialize the full hierarchy from the root. 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getHierarchyRoot().writeNodeContentsRecursive(dest); 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @VisibleForTesting 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public BookmarkNode getHierarchyRoot() { 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode root = this; 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (root.parent() != null) { 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) root = root.parent(); 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return root; 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private void writeNodeContentsRecursive(Parcel dest) { 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writeNodeContents(dest); 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest.writeInt(mChildren.size()); 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (BookmarkNode child : mChildren) { 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child.writeNodeContentsRecursive(dest); 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private void writeNodeContents(Parcel dest) { 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest.writeLong(mId); 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest.writeString(mName); 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest.writeString(mUrl); 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest.writeInt(mType.ordinal()); 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest.writeByteArray(mFavicon); 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest.writeByteArray(mThumbnail); 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest.writeLong(mParent != null ? mParent.mId : INVALID_BOOKMARK_ID); 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public static final Creator<BookmarkNode> CREATOR = new Creator<BookmarkNode>() { 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private HashMap<Long, BookmarkNode> mNodeMap; 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @Override 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public BookmarkNode createFromParcel(Parcel source) { 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mNodeMap = new HashMap<Long, BookmarkNode>(); 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long currentNodeId = source.readLong(); 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) readNodeContentsRecursive(source); 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode node = getNode(currentNodeId); 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mNodeMap.clear(); 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return node; 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @Override 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public BookmarkNode[] newArray(int size) { 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new BookmarkNode[size]; 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private BookmarkNode getNode(long id) { 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (id == INVALID_BOOKMARK_ID) return null; 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Long nodeId = Long.valueOf(id); 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!mNodeMap.containsKey(nodeId)) { 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Log.e(TAG, "Invalid BookmarkNode hierarchy. Unknown id " + id); 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return null; 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mNodeMap.get(nodeId); 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private BookmarkNode readNodeContents(Parcel source) { 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long id = source.readLong(); 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String name = source.readString(); 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String url = source.readString(); 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type = source.readInt(); 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) byte[] favicon = source.createByteArray(); 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) byte[] thumbnail = source.createByteArray(); 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long parentId = source.readLong(); 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type < 0 || type >= Type.values().length) { 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Log.w(TAG, "Invalid node type ordinal value."); 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return null; 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode node = new BookmarkNode(id, Type.values()[type], name, url, 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getNode(parentId)); 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node.setFavicon(favicon); 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node.setThumbnail(thumbnail); 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return node; 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private BookmarkNode readNodeContentsRecursive(Parcel source) { 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode node = readNodeContents(source); 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (node == null) return null; 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Long nodeId = Long.valueOf(node.id()); 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mNodeMap.containsKey(nodeId)) { 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Log.e(TAG, "Invalid BookmarkNode hierarchy. Duplicate id " + node.id()); 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return null; 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mNodeMap.put(nodeId, node); 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int numChildren = source.readInt(); 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < numChildren; ++i) { 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node.addChild(readNodeContentsRecursive(source)); 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return node; 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private long addBookmarkFromAPI(ContentValues values) { 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkRow row = BookmarkRow.fromContentValues(values); 10056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (row.mUrl == null) { 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw new IllegalArgumentException("Must have a bookmark URL"); 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return nativeAddBookmarkFromAPI(mNativeChromeBrowserProvider, 10096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) row.mUrl, row.mCreated, row.mIsBookmark, row.mDate, row.mFavicon, 10106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) row.mTitle, row.mVisits, row.mParentId); 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private Cursor queryBookmarkFromAPI(String[] projectionIn, String selection, 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String[] selectionArgs, String sortOrder) { 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String[] projection = null; 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (projectionIn == null || projectionIn.length == 0) { 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) projection = BOOKMARK_DEFAULT_PROJECTION; 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) projection = projectionIn; 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return nativeQueryBookmarkFromAPI(mNativeChromeBrowserProvider, projection, selection, 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selectionArgs, sortOrder); 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private int updateBookmarkFromAPI(ContentValues values, String selection, 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String[] selectionArgs) { 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkRow row = BookmarkRow.fromContentValues(values); 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return nativeUpdateBookmarkFromAPI(mNativeChromeBrowserProvider, 10306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) row.mUrl, row.mCreated, row.mIsBookmark, row.mDate, 10316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) row.mFavicon, row.mTitle, row.mVisits, row.mParentId, selection, selectionArgs); 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private int removeBookmarkFromAPI(String selection, String[] selectionArgs) { 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return nativeRemoveBookmarkFromAPI(mNativeChromeBrowserProvider, selection, selectionArgs); 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private int removeHistoryFromAPI(String selection, String[] selectionArgs) { 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return nativeRemoveHistoryFromAPI(mNativeChromeBrowserProvider, selection, selectionArgs); 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @CalledByNative 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private void onBookmarkChanged() { 1044a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) notifyChange(buildAPIContentUri(getContext(), BOOKMARKS_PATH)); 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @CalledByNative 10481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private void onHistoryChanged() { 10491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci notifyChange(buildAPIContentUri(getContext(), HISTORY_PATH)); 10501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 10511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 10521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci @CalledByNative 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private void onSearchTermChanged() { 1054a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) notifyChange(buildAPIContentUri(getContext(), SEARCHES_PATH)); 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private long addSearchTermFromAPI(ContentValues values) { 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SearchRow row = SearchRow.fromContentValues(values); 10596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (row.mTerm == null) { 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw new IllegalArgumentException("Must have a search term"); 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return nativeAddSearchTermFromAPI(mNativeChromeBrowserProvider, row.mTerm, row.mDate); 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private int updateSearchTermFromAPI(ContentValues values, String selection, 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String[] selectionArgs) { 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SearchRow row = SearchRow.fromContentValues(values); 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return nativeUpdateSearchTermFromAPI(mNativeChromeBrowserProvider, 10696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) row.mTerm, row.mDate, selection, selectionArgs); 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private Cursor querySearchTermFromAPI(String[] projectionIn, String selection, 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String[] selectionArgs, String sortOrder) { 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String[] projection = null; 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (projectionIn == null || projectionIn.length == 0) { 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) projection = android.provider.Browser.SEARCHES_PROJECTION; 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) projection = projectionIn; 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return nativeQuerySearchTermFromAPI(mNativeChromeBrowserProvider, projection, selection, 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selectionArgs, sortOrder); 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private int removeSearchFromAPI(String selection, String[] selectionArgs) { 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return nativeRemoveSearchTermFromAPI(mNativeChromeBrowserProvider, 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection, selectionArgs); 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static boolean isInUiThread() { 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ThreadUtils.runningOnUiThread()) return false; 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!"REL".equals(Build.VERSION.CODENAME)) { 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw new IllegalStateException("Shouldn't run in the UI thread"); 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Log.w(TAG, "ChromeBrowserProvider methods cannot be called from the UI thread."); 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static Uri buildContentUri(String authority, String path) { 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Uri.parse("content://" + authority + "/" + path); 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static Uri buildAPIContentUri(Context context, String path) { 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buildContentUri(context.getPackageName() + API_AUTHORITY_SUFFIX, path); 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static String buildWhereClause(long id, String selection) { 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringBuffer sb = new StringBuffer(); 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sb.append(BaseColumns._ID); 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sb.append(" = "); 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sb.append(id); 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!TextUtils.isEmpty(selection)) { 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sb.append(" AND ("); 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sb.append(selection); 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sb.append(")"); 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sb.toString(); 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static String buildHistoryWhereClause(long id, String selection) { 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buildWhereClause(id, buildBookmarkWhereClause(selection, false)); 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static String buildHistoryWhereClause(String selection) { 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buildBookmarkWhereClause(selection, false); 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return a SQL where class which is inserted the bookmark condition. 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private static String buildBookmarkWhereClause(String selection, boolean isBookmark) { 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringBuffer sb = new StringBuffer(); 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sb.append(BookmarkColumns.BOOKMARK); 1135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) sb.append(isBookmark ? " = 1 " : " = 0"); 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!TextUtils.isEmpty(selection)) { 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sb.append(" AND ("); 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sb.append(selection); 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sb.append(")"); 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sb.toString(); 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static String buildBookmarkWhereClause(long id, String selection) { 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buildWhereClause(id, buildBookmarkWhereClause(selection, true)); 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static String buildBookmarkWhereClause(String selection) { 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buildBookmarkWhereClause(selection, true); 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wrap the value of BookmarkColumn. 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static class BookmarkRow { 11546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) Boolean mIsBookmark; 11556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) Long mCreated; 11566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) String mUrl; 11576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) Long mDate; 11586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) byte[] mFavicon; 11596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) String mTitle; 11606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) Integer mVisits; 11616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) long mParentId; 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static BookmarkRow fromContentValues(ContentValues values) { 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkRow row = new BookmarkRow(); 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (values.containsKey(BookmarkColumns.URL)) { 11666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) row.mUrl = values.getAsString(BookmarkColumns.URL); 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (values.containsKey(BookmarkColumns.BOOKMARK)) { 11696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) row.mIsBookmark = values.getAsInteger(BookmarkColumns.BOOKMARK) != 0; 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (values.containsKey(BookmarkColumns.CREATED)) { 11726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) row.mCreated = values.getAsLong(BookmarkColumns.CREATED); 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (values.containsKey(BookmarkColumns.DATE)) { 11756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) row.mDate = values.getAsLong(BookmarkColumns.DATE); 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (values.containsKey(BookmarkColumns.FAVICON)) { 11786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) row.mFavicon = values.getAsByteArray(BookmarkColumns.FAVICON); 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to know that the caller set the favicon column. 11806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (row.mFavicon == null) { 11816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) row.mFavicon = new byte[0]; 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (values.containsKey(BookmarkColumns.TITLE)) { 11856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) row.mTitle = values.getAsString(BookmarkColumns.TITLE); 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (values.containsKey(BookmarkColumns.VISITS)) { 11886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) row.mVisits = values.getAsInteger(BookmarkColumns.VISITS); 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (values.containsKey(BOOKMARK_PARENT_ID_PARAM)) { 11916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) row.mParentId = values.getAsLong(BOOKMARK_PARENT_ID_PARAM); 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return row; 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wrap the value of SearchColumn. 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static class SearchRow { 11996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) String mTerm; 12006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) Long mDate; 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static SearchRow fromContentValues(ContentValues values) { 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SearchRow row = new SearchRow(); 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (values.containsKey(SearchColumns.SEARCH)) { 12056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) row.mTerm = values.getAsString(SearchColumns.SEARCH); 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (values.containsKey(SearchColumns.DATE)) { 12086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) row.mDate = values.getAsLong(SearchColumns.DATE); 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return row; 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns true if the native side of the class is initialized. 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected boolean isNativeSideInitialized() { 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mNativeChromeBrowserProvider != 0; 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Make sure chrome is running. This method mustn't run on UI thread. 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return Whether the native chrome process is running successfully once this has returned. 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private boolean ensureNativeChromeLoaded() { 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ensureUriMatcherInitialized(); 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) synchronized (mLoadNativeLock) { 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mNativeChromeBrowserProvider != 0) return true; 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) final AtomicBoolean retVal = new AtomicBoolean(true); 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadUtils.runOnUiThreadBlocking(new Runnable() { 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @Override 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public void run() { 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) retVal.set(ensureNativeChromeLoadedOnUIThread()); 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }); 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return retVal.get(); 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This method should only run on UI thread. 12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected boolean ensureNativeChromeLoadedOnUIThread() { 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isNativeSideInitialized()) return true; 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mNativeChromeBrowserProvider = nativeInit(); 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return isNativeSideInitialized(); 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @Override 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected void finalize() throws Throwable { 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try { 12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tests might try to destroy this in the wrong thread. 12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadUtils.runOnUiThreadBlocking(new Runnable() { 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @Override 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public void run() { 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ensureNativeChromeDestroyedOnUIThread(); 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }); 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } finally { 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) super.finalize(); 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This method should only run on UI thread. 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private void ensureNativeChromeDestroyedOnUIThread() { 12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isNativeSideInitialized()) { 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nativeDestroy(mNativeChromeBrowserProvider); 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mNativeChromeBrowserProvider = 0; 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) @SuppressLint("NewApi") 1278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private void notifyChange(final Uri uri) { 1279a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // If the calling user is different than current one, we need to post a 1280a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // task to notify change, otherwise, a system level hidden permission 1281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // INTERACT_ACROSS_USERS_FULL is needed. 1282a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // The related APIs were added in API 17, it should be safe to fallback to 1283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // normal way for notifying change, because caller can't be other users in 1284a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // devices whose API level is less than API 17. 1285a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { 1286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) UserHandle callingUserHandle = Binder.getCallingUserHandle(); 1287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (callingUserHandle != null && 1288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) !callingUserHandle.equals(android.os.Process.myUserHandle())) { 1289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ThreadUtils.postOnUiThread(new Runnable() { 1290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) @Override 1291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public void run() { 1292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) getContext().getContentResolver().notifyChange(uri, null); 1293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }); 1295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 1296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) getContext().getContentResolver().notifyChange(uri, null); 1299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1301f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native long nativeInit(); 1302f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native void nativeDestroy(long nativeChromeBrowserProvider); 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Public API native methods. 1305f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native long nativeAddBookmark(long nativeChromeBrowserProvider, 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String url, String title, boolean isFolder, long parentId); 13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1308f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native int nativeRemoveBookmark(long nativeChromeBrowserProvider, long id); 13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1310f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native int nativeUpdateBookmark(long nativeChromeBrowserProvider, 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long id, String url, String title, long parentId); 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1313f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native long nativeAddBookmarkFromAPI(long nativeChromeBrowserProvider, 13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String url, Long created, Boolean isBookmark, Long date, byte[] favicon, 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String title, Integer visits, long parentId); 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1317f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native SQLiteCursor nativeQueryBookmarkFromAPI(long nativeChromeBrowserProvider, 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String[] projection, String selection, String[] selectionArgs, String sortOrder); 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1320f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native int nativeUpdateBookmarkFromAPI(long nativeChromeBrowserProvider, 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String url, Long created, Boolean isBookmark, Long date, byte[] favicon, 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String title, Integer visits, long parentId, String selection, String[] selectionArgs); 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1324f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native int nativeRemoveBookmarkFromAPI(long nativeChromeBrowserProvider, 13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String selection, String[] selectionArgs); 13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native int nativeRemoveHistoryFromAPI(long nativeChromeBrowserProvider, 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String selection, String[] selectionArgs); 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1330f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native long nativeAddSearchTermFromAPI(long nativeChromeBrowserProvider, 13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String term, Long date); 13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1333f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native SQLiteCursor nativeQuerySearchTermFromAPI(long nativeChromeBrowserProvider, 13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String[] projection, String selection, String[] selectionArgs, String sortOrder); 13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native int nativeUpdateSearchTermFromAPI(long nativeChromeBrowserProvider, 13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String search, Long date, String selection, String[] selectionArgs); 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1339f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native int nativeRemoveSearchTermFromAPI(long nativeChromeBrowserProvider, 13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String selection, String[] selectionArgs); 13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Client API native methods. 1343f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native boolean nativeBookmarkNodeExists(long nativeChromeBrowserProvider, long id); 13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native long nativeCreateBookmarksFolderOnce(long nativeChromeBrowserProvider, 13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) String title, long parentId); 13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1348f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private native BookmarkNode nativeGetEditableBookmarkFolders(long nativeChromeBrowserProvider); 13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1350f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private native void nativeRemoveAllUserBookmarks(long nativeChromeBrowserProvider); 1351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1352f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native BookmarkNode nativeGetBookmarkNode(long nativeChromeBrowserProvider, 13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long id, boolean getParent, boolean getChildren); 13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native BookmarkNode nativeGetMobileBookmarksFolder(long nativeChromeBrowserProvider); 13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1357f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native boolean nativeIsBookmarkInMobileBookmarksBranch(long nativeChromeBrowserProvider, 13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long id); 13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1360f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native byte[] nativeGetFaviconOrTouchIcon(long nativeChromeBrowserProvider, String url); 13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native byte[] nativeGetThumbnail(long nativeChromeBrowserProvider, String url); 13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1364