Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / android / java / src / org / chromium / chrome / browser / ChromeBrowserProvider.java
index 8d7076a..add6afe 100644 (file)
@@ -4,17 +4,16 @@
 
 package org.chromium.chrome.browser;
 
+import android.annotation.SuppressLint;
 import android.app.SearchManager;
 import android.content.ContentProvider;
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
-import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.UriMatcher;
 import android.database.Cursor;
 import android.database.MatrixCursor;
-import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Build;
@@ -30,11 +29,10 @@ import android.provider.Browser.SearchColumns;
 import android.text.TextUtils;
 import android.util.Log;
 
-import com.google.common.annotations.VisibleForTesting;
-
 import org.chromium.base.CalledByNative;
 import org.chromium.base.CalledByNativeUnchecked;
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.browser.database.SQLiteCursor;
 import org.chromium.sync.notifier.SyncStatusHelper;
 
@@ -46,9 +44,8 @@ import java.util.Vector;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
- * This class provides various information of Chrome, like bookmarks, most
- * visited page etc. It is used to support android.provider.Browser.
- *
+ * This class provides access to user data stored in Chrome, such as bookmarks, most visited pages,
+ * etc. It is used to support android.provider.Browser.
  */
 public class ChromeBrowserProvider extends ContentProvider {
     private static final String TAG = "ChromeBrowserProvider";
@@ -61,14 +58,15 @@ public class ChromeBrowserProvider extends ContentProvider {
     // Defines the API methods that the Client can call by name.
     static final String CLIENT_API_BOOKMARK_NODE_EXISTS = "BOOKMARK_NODE_EXISTS";
     static final String CLIENT_API_CREATE_BOOKMARKS_FOLDER_ONCE = "CREATE_BOOKMARKS_FOLDER_ONCE";
-    static final String CLIENT_API_GET_BOOKMARK_FOLDER_HIERARCHY = "GET_BOOKMARK_FOLDER_HIERARCHY";
+    static final String CLIENT_API_GET_EDITABLE_BOOKMARK_FOLDER_HIERARCHY =
+            "GET_EDITABLE_BOOKMARK_FOLDER_HIERARCHY";
     static final String CLIENT_API_GET_BOOKMARK_NODE = "GET_BOOKMARK_NODE";
     static final String CLIENT_API_GET_DEFAULT_BOOKMARK_FOLDER = "GET_DEFAULT_BOOKMARK_FOLDER";
     static final String CLIENT_API_GET_MOBILE_BOOKMARKS_FOLDER_ID =
             "GET_MOBILE_BOOKMARKS_FOLDER_ID";
     static final String CLIENT_API_IS_BOOKMARK_IN_MOBILE_BOOKMARKS_BRANCH =
             "IS_BOOKMARK_IN_MOBILE_BOOKMARKS_BRANCH";
-    static final String CLIENT_API_DELETE_ALL_BOOKMARKS = "DELETE_ALL_BOOKMARKS";
+    static final String CLIENT_API_DELETE_ALL_USER_BOOKMARKS = "DELETE_ALL_USER_BOOKMARKS";
     static final String CLIENT_API_RESULT_KEY = "result";
 
 
@@ -115,7 +113,11 @@ public class ChromeBrowserProvider extends ContentProvider {
     /** The parameter used to specify whether this is a bookmark folder. */
     public static final String BOOKMARK_IS_FOLDER_PARAM = "isFolder";
 
-    /** Invalid id value for the Android ContentProvider API calls. */
+    /**
+     * Invalid ID value for the Android ContentProvider API calls.
+     * The value 0 is intentional: if the ID represents a bookmark node then it's the root node
+     * and not accessible. Otherwise it represents a SQLite row id, so 0 is also invalid.
+     */
     public static final long INVALID_CONTENT_PROVIDER_ID = 0;
 
     // ID used to indicate an invalid id for bookmark nodes.
@@ -303,20 +305,28 @@ public class ChromeBrowserProvider extends ContentProvider {
         return new ChromeBrowserProviderSuggestionsCursor(cursor);
     }
 
+    /**
+     * @see android.content.ContentUris#parseId(Uri)
+     * @return The id from a content URI or -1 if the URI has no id or is malformed.
+     */
+    private static long getContentUriId(Uri uri) {
+        try {
+            return ContentUris.parseId(uri);
+        } catch (UnsupportedOperationException e) {
+            return -1;
+        } catch (NumberFormatException e) {
+            return -1;
+        }
+    }
+
     @Override
     public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
             String sortOrder) {
         if (!canHandleContentProviderApiCall()) return null;
 
         // Check for invalid id values if provided.
-        // If it represents a bookmark node then it's the root node. Don't provide access here.
-        // Otherwise it represents a SQLite row id, so 0 is invalid.
-        long bookmarkId = INVALID_CONTENT_PROVIDER_ID;
-        try {
-            bookmarkId = ContentUris.parseId(uri);
-            if (bookmarkId == INVALID_CONTENT_PROVIDER_ID) return null;
-        } catch (Exception e) {
-        }
+        long bookmarkId = getContentUriId(uri);
+        if (bookmarkId == INVALID_CONTENT_PROVIDER_ID) return null;
 
         int match = mUriMatcher.match(uri);
         Cursor cursor = null;
@@ -405,14 +415,8 @@ public class ChromeBrowserProvider extends ContentProvider {
         if (!canHandleContentProviderApiCall()) return 0;
 
         // Check for invalid id values if provided.
-        // If it represents a bookmark node then it's the root node and not mutable.
-        // Otherwise it represents a SQLite row id, so 0 is invalid.
-        long bookmarkId = INVALID_CONTENT_PROVIDER_ID;
-        try {
-            bookmarkId = ContentUris.parseId(uri);
-            if (bookmarkId == INVALID_CONTENT_PROVIDER_ID) return 0;
-        } catch (Exception e) {
-        }
+        long bookmarkId = getContentUriId(uri);
+        if (bookmarkId == INVALID_CONTENT_PROVIDER_ID) return 0;
 
         int match = mUriMatcher.match(uri);
         int result;
@@ -460,14 +464,8 @@ public class ChromeBrowserProvider extends ContentProvider {
         if (!canHandleContentProviderApiCall()) return 0;
 
         // Check for invalid id values if provided.
-        // If it represents a bookmark node then it's the root node and not mutable.
-        // Otherwise it represents a SQLite row id, so 0 is invalid.
-        long bookmarkId = INVALID_CONTENT_PROVIDER_ID;
-        try {
-            bookmarkId = ContentUris.parseId(uri);
-            if (bookmarkId == INVALID_CONTENT_PROVIDER_ID) return 0;
-        } catch (Exception e) {
-        }
+        long bookmarkId = getContentUriId(uri);
+        if (bookmarkId == INVALID_CONTENT_PROVIDER_ID) return 0;
 
         int match = mUriMatcher.match(uri);
         int result;
@@ -613,8 +611,8 @@ public class ChromeBrowserProvider extends ContentProvider {
         return nativeCreateBookmarksFolderOnce(mNativeChromeBrowserProvider, title, parentId);
     }
 
-    private BookmarkNode getBookmarkFolderHierarchy() {
-        return nativeGetAllBookmarkFolders(mNativeChromeBrowserProvider);
+    private BookmarkNode getEditableBookmarkFolderHierarchy() {
+        return nativeGetEditableBookmarkFolders(mNativeChromeBrowserProvider);
     }
 
     protected BookmarkNode getBookmarkNode(long nodeId, boolean getParent, boolean getChildren,
@@ -645,7 +643,7 @@ public class ChromeBrowserProvider extends ContentProvider {
         // then use the synced node (Mobile Bookmarks).
         BookmarkNode lastModified = getBookmarkNode(getLastModifiedBookmarkFolderId(), false, false,
                 false, false);
-        if (lastModified == null) {
+        if (lastModified == null || lastModified.isUrl()) {
             lastModified = getMobileBookmarksFolder();
             mLastModifiedBookmarkFolderId = lastModified != null ? lastModified.id() :
                     INVALID_BOOKMARK_ID;
@@ -703,8 +701,8 @@ public class ChromeBrowserProvider extends ContentProvider {
             result.putLong(CLIENT_API_RESULT_KEY,
                     createBookmarksFolderOnce(extras.getString(argKey(0)),
                                               extras.getLong(argKey(1))));
-        } else if (CLIENT_API_GET_BOOKMARK_FOLDER_HIERARCHY.equals(method)) {
-            result.putParcelable(CLIENT_API_RESULT_KEY, getBookmarkFolderHierarchy());
+        } else if (CLIENT_API_GET_EDITABLE_BOOKMARK_FOLDER_HIERARCHY.equals(method)) {
+            result.putParcelable(CLIENT_API_RESULT_KEY, getEditableBookmarkFolderHierarchy());
         } else if (CLIENT_API_GET_BOOKMARK_NODE.equals(method)) {
             result.putParcelable(CLIENT_API_RESULT_KEY,
                     getBookmarkNode(extras.getLong(argKey(0)),
@@ -719,8 +717,8 @@ public class ChromeBrowserProvider extends ContentProvider {
         } else if (CLIENT_API_IS_BOOKMARK_IN_MOBILE_BOOKMARKS_BRANCH.equals(method)) {
             result.putBoolean(CLIENT_API_RESULT_KEY,
                     isBookmarkInMobileBookmarksBranch(extras.getLong(argKey(0))));
-        } else if (CLIENT_API_DELETE_ALL_BOOKMARKS.equals(method)) {
-            nativeRemoveAllBookmarks(mNativeChromeBrowserProvider);
+        } else if (CLIENT_API_DELETE_ALL_USER_BOOKMARKS.equals(method)) {
+            nativeRemoveAllUserBookmarks(mNativeChromeBrowserProvider);
         } else {
             Log.w(TAG, "Received invalid method " + method);
             return null;
@@ -1004,12 +1002,12 @@ public class ChromeBrowserProvider extends ContentProvider {
 
     private long addBookmarkFromAPI(ContentValues values) {
         BookmarkRow row = BookmarkRow.fromContentValues(values);
-        if (row.url == null) {
+        if (row.mUrl == null) {
             throw new IllegalArgumentException("Must have a bookmark URL");
         }
         return nativeAddBookmarkFromAPI(mNativeChromeBrowserProvider,
-                row.url, row.created, row.isBookmark, row.date, row.favicon,
-                row.title, row.visits, row.parentId);
+                row.mUrl, row.mCreated, row.mIsBookmark, row.mDate, row.mFavicon,
+                row.mTitle, row.mVisits, row.mParentId);
     }
 
     private Cursor queryBookmarkFromAPI(String[] projectionIn, String selection,
@@ -1029,8 +1027,8 @@ public class ChromeBrowserProvider extends ContentProvider {
             String[] selectionArgs) {
         BookmarkRow row = BookmarkRow.fromContentValues(values);
         return nativeUpdateBookmarkFromAPI(mNativeChromeBrowserProvider,
-                row.url, row.created, row.isBookmark, row.date,
-                row.favicon, row.title, row.visits, row.parentId, selection, selectionArgs);
+                row.mUrl, row.mCreated, row.mIsBookmark, row.mDate,
+                row.mFavicon, row.mTitle, row.mVisits, row.mParentId, selection, selectionArgs);
     }
 
     private int removeBookmarkFromAPI(String selection, String[] selectionArgs) {
@@ -1047,23 +1045,28 @@ public class ChromeBrowserProvider extends ContentProvider {
     }
 
     @CalledByNative
+    private void onHistoryChanged() {
+        notifyChange(buildAPIContentUri(getContext(), HISTORY_PATH));
+    }
+
+    @CalledByNative
     private void onSearchTermChanged() {
         notifyChange(buildAPIContentUri(getContext(), SEARCHES_PATH));
     }
 
     private long addSearchTermFromAPI(ContentValues values) {
         SearchRow row = SearchRow.fromContentValues(values);
-        if (row.term == null) {
+        if (row.mTerm == null) {
             throw new IllegalArgumentException("Must have a search term");
         }
-        return nativeAddSearchTermFromAPI(mNativeChromeBrowserProvider, row.term, row.date);
+        return nativeAddSearchTermFromAPI(mNativeChromeBrowserProvider, row.mTerm, row.mDate);
     }
 
     private int updateSearchTermFromAPI(ContentValues values, String selection,
             String[] selectionArgs) {
         SearchRow row = SearchRow.fromContentValues(values);
         return nativeUpdateSearchTermFromAPI(mNativeChromeBrowserProvider,
-                row.term, row.date, selection, selectionArgs);
+                row.mTerm, row.mDate, selection, selectionArgs);
     }
 
     private Cursor querySearchTermFromAPI(String[] projectionIn, String selection,
@@ -1148,44 +1151,44 @@ public class ChromeBrowserProvider extends ContentProvider {
 
     // Wrap the value of BookmarkColumn.
     private static class BookmarkRow {
-        Boolean isBookmark;
-        Long created;
-        String url;
-        Long date;
-        byte[] favicon;
-        String title;
-        Integer visits;
-        long parentId;
+        Boolean mIsBookmark;
+        Long mCreated;
+        String mUrl;
+        Long mDate;
+        byte[] mFavicon;
+        String mTitle;
+        Integer mVisits;
+        long mParentId;
 
         static BookmarkRow fromContentValues(ContentValues values) {
             BookmarkRow row = new BookmarkRow();
             if (values.containsKey(BookmarkColumns.URL)) {
-                row.url = values.getAsString(BookmarkColumns.URL);
+                row.mUrl = values.getAsString(BookmarkColumns.URL);
             }
             if (values.containsKey(BookmarkColumns.BOOKMARK)) {
-                row.isBookmark = values.getAsInteger(BookmarkColumns.BOOKMARK) != 0;
+                row.mIsBookmark = values.getAsInteger(BookmarkColumns.BOOKMARK) != 0;
             }
             if (values.containsKey(BookmarkColumns.CREATED)) {
-                row.created = values.getAsLong(BookmarkColumns.CREATED);
+                row.mCreated = values.getAsLong(BookmarkColumns.CREATED);
             }
             if (values.containsKey(BookmarkColumns.DATE)) {
-                row.date = values.getAsLong(BookmarkColumns.DATE);
+                row.mDate = values.getAsLong(BookmarkColumns.DATE);
             }
             if (values.containsKey(BookmarkColumns.FAVICON)) {
-                row.favicon = values.getAsByteArray(BookmarkColumns.FAVICON);
+                row.mFavicon = values.getAsByteArray(BookmarkColumns.FAVICON);
                 // We need to know that the caller set the favicon column.
-                if (row.favicon == null) {
-                    row.favicon = new byte[0];
+                if (row.mFavicon == null) {
+                    row.mFavicon = new byte[0];
                 }
             }
             if (values.containsKey(BookmarkColumns.TITLE)) {
-                row.title = values.getAsString(BookmarkColumns.TITLE);
+                row.mTitle = values.getAsString(BookmarkColumns.TITLE);
             }
             if (values.containsKey(BookmarkColumns.VISITS)) {
-                row.visits = values.getAsInteger(BookmarkColumns.VISITS);
+                row.mVisits = values.getAsInteger(BookmarkColumns.VISITS);
             }
             if (values.containsKey(BOOKMARK_PARENT_ID_PARAM)) {
-                row.parentId = values.getAsLong(BOOKMARK_PARENT_ID_PARAM);
+                row.mParentId = values.getAsLong(BOOKMARK_PARENT_ID_PARAM);
             }
             return row;
         }
@@ -1193,16 +1196,16 @@ public class ChromeBrowserProvider extends ContentProvider {
 
     // Wrap the value of SearchColumn.
     private static class SearchRow {
-        String term;
-        Long date;
+        String mTerm;
+        Long mDate;
 
         static SearchRow fromContentValues(ContentValues values) {
             SearchRow row = new SearchRow();
             if (values.containsKey(SearchColumns.SEARCH)) {
-                row.term = values.getAsString(SearchColumns.SEARCH);
+                row.mTerm = values.getAsString(SearchColumns.SEARCH);
             }
             if (values.containsKey(SearchColumns.DATE)) {
-                row.date = values.getAsLong(SearchColumns.DATE);
+                row.mDate = values.getAsLong(SearchColumns.DATE);
             }
             return row;
         }
@@ -1271,15 +1274,7 @@ public class ChromeBrowserProvider extends ContentProvider {
         }
     }
 
-    /**
-     * Call to get the intent to create a bookmark shortcut on homescreen.
-     */
-    public static Intent getShortcutToBookmark(String url, String title, Bitmap favicon, int rValue,
-            int gValue, int bValue, Context context) {
-        return BookmarkUtils.createAddToHomeIntent(
-                context, url, title, favicon, rValue, gValue, bValue);
-    }
-
+    @SuppressLint("NewApi")
     private void notifyChange(final Uri uri) {
         // If the calling user is different than current one, we need to post a
         // task to notify change, otherwise, a system level hidden permission
@@ -1350,9 +1345,9 @@ public class ChromeBrowserProvider extends ContentProvider {
     private native long nativeCreateBookmarksFolderOnce(long nativeChromeBrowserProvider,
             String title, long parentId);
 
-    private native BookmarkNode nativeGetAllBookmarkFolders(long nativeChromeBrowserProvider);
+    private native BookmarkNode nativeGetEditableBookmarkFolders(long nativeChromeBrowserProvider);
 
-    private native void nativeRemoveAllBookmarks(long nativeChromeBrowserProvider);
+    private native void nativeRemoveAllUserBookmarks(long nativeChromeBrowserProvider);
 
     private native BookmarkNode nativeGetBookmarkNode(long nativeChromeBrowserProvider,
             long id, boolean getParent, boolean getChildren);