Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1179)

Unified Diff: chrome/android/java_staging/src/org/chromium/chrome/browser/bookmarkimport/BookmarkImporter.java

Issue 1206673003: Merge java_staging/src into java/src. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/android/java_staging/src/org/chromium/chrome/browser/bookmarkimport/BookmarkImporter.java
diff --git a/chrome/android/java_staging/src/org/chromium/chrome/browser/bookmarkimport/BookmarkImporter.java b/chrome/android/java_staging/src/org/chromium/chrome/browser/bookmarkimport/BookmarkImporter.java
deleted file mode 100644
index cc851130921fdb6b0e67fa2b43ccd16bbf80c2f0..0000000000000000000000000000000000000000
--- a/chrome/android/java_staging/src/org/chromium/chrome/browser/bookmarkimport/BookmarkImporter.java
+++ /dev/null
@@ -1,364 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.bookmarkimport;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.provider.Browser;
-import android.provider.Browser.BookmarkColumns;
-import android.util.Log;
-
-import org.chromium.chrome.browser.ChromeBrowserProvider;
-import org.chromium.chrome.browser.ChromeBrowserProviderClient;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-
-/**
- * Imports bookmarks from another browser into Chrome.
- */
-public abstract class BookmarkImporter {
- private static final String TAG = "BookmarkImporter";
-
- /** Class containing the results of a bookmark import operation */
- public static class ImportResults {
- public int newBookmarks; // Number of new bookmarks that could be imported.
- public int numImported; // Number of bookmarks that were successfully imported.
- public long rootFolderId; // ID of the folder where the bookmarks were imported.
- }
-
- /** Listener for asynchronous import events. */
- public interface OnBookmarksImportedListener {
- /**
- * Triggered after finishing the bookmark importing operation.
- * @param results Results of the importing operation. Will be null in case of failure.
- */
- public void onBookmarksImported(ImportResults results);
- }
-
- /** Object defining an imported bookmark. */
- static class Bookmark {
- // To be provided by the bookmark extractors.
- public long id; // Local id of the imported bookmark. Value ROOT_FOLDER_ID is reserved.
- public long parentId; // Import id of the parent node.
- public boolean isFolder; // True if the object describes a bookmark folder.
- public String url; // URL of the bookmark. Required for non-folders.
- public String title; // Title of the bookmark.
- public Long created; // Creation date (timestamp) of the bookmark. Optional.
- public Long lastVisit; // Date (timestamp) of the last visit. Optional.
- public Long visits; // Number of visits to the page. Optional.
- public byte[] favicon; // Favicon of the bookmark. Optional.
-
- // For auxiliary use while importing. Not to be set by the bookmark extractors.
- public long nativeId;
- public Bookmark parent;
- public ArrayList<Bookmark> entries = new ArrayList<Bookmark>();
- public boolean processed;
- }
-
- /** Closable iterator for available bookmarks. */
- public interface BookmarkIterator extends Iterator<Bookmark> {
- public void close();
- }
-
- /**
- * Returns an array of iterators to the available bookmarks.
- * The first one is tried and in case of complete importing failure the second one is then used
- * and so on until the array is exhausted. Note that no new bookmarks is not a failure.
- *
- * Called by an async task.
- */
- protected abstract BookmarkIterator[] availableBookmarks();
-
- /** Imported bookmark id reserved for the root folder. */
- static final long ROOT_FOLDER_ID = 0;
-
- // Auxiliary query constants.
- private static final Integer VALUE_IS_BOOKMARK = 1;
- private static final String SELECT_IS_BOOKMARK = Browser.BookmarkColumns.BOOKMARK + "="
- + VALUE_IS_BOOKMARK.toString();
- private static final String HAS_URL = Browser.BookmarkColumns.URL + "=?";
- private static final String[] EXISTS_PROJECTION = new String[]{ BookmarkColumns.URL };
-
- protected final Context mContext;
-
- private ImportBookmarksTask mTask;
-
- protected BookmarkImporter(Context context) {
- mContext = context;
- }
-
- /** Asynchronously import bookmarks from another browser */
- public void importBookmarks(OnBookmarksImportedListener listener) {
- mTask = new ImportBookmarksTask(listener);
- mTask.execute();
- }
-
- public void cancel() {
- mTask.cancel(true);
- }
-
- /**
- * Handles loading Android Browser bookmarks in a background thread.
- */
- private class ImportBookmarksTask extends AsyncTask<Void, Void, ImportResults> {
- private final OnBookmarksImportedListener mBookmarksImportedListener;
-
- ImportBookmarksTask(OnBookmarksImportedListener listener) {
- mBookmarksImportedListener = listener;
- }
-
- @Override
- protected ImportResults doInBackground(Void... params) {
- BookmarkIterator[] iterators = null;
- try {
- iterators = availableBookmarks();
- } catch (Exception e) {
- Log.w(TAG, "Unexpected exception while requesting available bookmarks: "
- + e.getMessage());
- return null;
- }
-
- if (iterators == null) {
- Log.e(TAG, "No bookmark iterators found.");
- return null;
- }
-
- for (BookmarkIterator iterator : iterators) {
- ImportResults results = importFromIterator(iterator);
- if (results != null) return results;
- }
-
- return null;
- }
-
- @Override
- protected void onPostExecute(ImportResults results) {
- if (mBookmarksImportedListener != null) {
- mBookmarksImportedListener.onBookmarksImported(results);
- }
- }
-
- private ImportResults importFromIterator(BookmarkIterator bookmarkIterator) {
- try {
- if (bookmarkIterator == null) return null;
-
- // Get a snapshot of the bookmarks.
- LinkedHashMap<Long, Bookmark> idMap = new LinkedHashMap<Long, Bookmark>();
- HashSet<String> urlSet = new HashSet<String>();
-
- // The root folder is used for hierarchy reconstruction purposes only.
- // Bookmarks are directly imported into the Mobile Bookmarks folder.
- Bookmark rootFolder = createRootFolderBookmark();
- idMap.put(ROOT_FOLDER_ID, rootFolder);
-
- int failedImports = 0;
- while (bookmarkIterator.hasNext()) {
- Bookmark bookmark = bookmarkIterator.next();
- if (bookmark == null) {
- ++failedImports;
- continue;
- }
-
- // Check for duplicate ids.
- if (idMap.containsKey(bookmark.id)) {
- Log.e(TAG, "Duplicate bookmark id: " + bookmark.id
- + ". Dropping bookmark.");
- ++failedImports;
- continue;
- }
-
- // Check for duplicate URLs.
- if (!bookmark.isFolder && urlSet.contains(bookmark.url)) {
- Log.i(TAG, "More than one bookmark pointing to " + bookmark.url
- + ". Keeping only the first one for consistency with Chromium.");
- continue;
- }
-
- // Reject bookmarks that already exist in the native model.
- if (alreadyExists(bookmark)) continue;
-
- idMap.put(bookmark.id, bookmark);
- urlSet.add(bookmark.url);
- }
- bookmarkIterator.close();
-
- // Abort if no new bookmarks to import.
- ImportResults results = new ImportResults();
- results.rootFolderId = rootFolder.nativeId;
- results.newBookmarks = idMap.size() + failedImports - 1;
- if (results.newBookmarks == 0) return results;
-
- // Check if all imports failed.
- if (idMap.size() == 1 && failedImports > 0) return null;
-
- // Recreate the folder hierarchy and import it.
- recreateFolderHierarchy(idMap);
- importBookmarkHierarchy(rootFolder, results);
-
- return results;
- } catch (Exception e) {
- Log.w(TAG, "Unexpected exception while importing bookmarks: " + e.getMessage());
- return null;
- }
- }
-
- private ContentValues getBookmarkValues(Bookmark bookmark) {
- ContentValues values = new ContentValues();
- values.put(BookmarkColumns.BOOKMARK, VALUE_IS_BOOKMARK);
- values.put(BookmarkColumns.URL, bookmark.url);
- values.put(BookmarkColumns.TITLE, bookmark.title);
- values.put(ChromeBrowserProvider.BOOKMARK_PARENT_ID_PARAM, bookmark.parent.nativeId);
- if (bookmark.created != null) values.put(BookmarkColumns.CREATED, bookmark.created);
- if (bookmark.lastVisit != null) values.put(BookmarkColumns.DATE, bookmark.lastVisit);
- if (bookmark.visits != null) {
- // TODO(michaelbai) http://crbug.com/149376, http://b/6362473
- // See android_provider_backend.cc IsHistoryAndBookmarkRowValid().
- if (bookmark.created != null && bookmark.lastVisit != null
- && bookmark.visits.longValue() > 2
- && bookmark.lastVisit.longValue() - bookmark.created.longValue()
- > bookmark.visits.longValue()) {
- values.put(BookmarkColumns.VISITS, bookmark.visits);
- }
- }
- if (bookmark.favicon != null) values.put(BookmarkColumns.FAVICON, bookmark.favicon);
- return values;
- }
-
- private boolean alreadyExists(Bookmark bookmark) {
- // Folders are re-used if they already exist. No need to filter them out.
- if (bookmark.isFolder) return false;
-
- Cursor cursor = mContext.getContentResolver().query(
- ChromeBrowserProvider.getBookmarksApiUri(mContext), EXISTS_PROJECTION,
- SELECT_IS_BOOKMARK + " AND " + HAS_URL, new String[]{ bookmark.url }, null);
- if (cursor != null) {
- boolean exists = cursor.getCount() > 0;
- cursor.close();
- return exists;
- }
- return false;
- }
-
- private void recreateFolderHierarchy(LinkedHashMap<Long, Bookmark> idMap) {
- for (Bookmark bookmark : idMap.values()) {
- if (bookmark.id == ROOT_FOLDER_ID) continue;
-
- // Look for invalid parent ids and self-cycles.
- if (!idMap.containsKey(bookmark.parentId) || bookmark.parentId == bookmark.id) {
- bookmark.parent = idMap.get(ROOT_FOLDER_ID);
- bookmark.parent.entries.add(bookmark);
- continue;
- }
-
- bookmark.parent = idMap.get(bookmark.parentId);
- bookmark.parent.entries.add(bookmark);
- }
- }
-
- private Bookmark createRootFolderBookmark() {
- Bookmark root = new Bookmark();
- root.id = ROOT_FOLDER_ID;
- root.nativeId = ChromeBrowserProviderClient.getMobileBookmarksFolderId(mContext);
- root.parentId = ROOT_FOLDER_ID;
- root.parent = root;
- root.isFolder = true;
- return root;
- }
-
- private void importBookmarkHierarchy(Bookmark bookmark, ImportResults results) {
- // Avoid cycles in the hierarchy that could lead to infinite loops.
- if (bookmark.processed) return;
- bookmark.processed = true;
-
- if (bookmark.isFolder) {
- if (bookmark.id != ROOT_FOLDER_ID) {
- bookmark.nativeId = ChromeBrowserProviderClient.createBookmarksFolderOnce(
- mContext, bookmark.title, bookmark.parent.nativeId);
- ++results.numImported;
- }
-
- if (bookmark.nativeId == ChromeBrowserProviderClient.INVALID_BOOKMARK_ID
- && bookmark.id != ROOT_FOLDER_ID) {
- Log.e(TAG, "Error creating the folder '" + bookmark.title
- + "'. Skipping entries.");
- return;
- }
-
- for (Bookmark entry : bookmark.entries) {
- if (entry.parent != bookmark) {
- Log.w(TAG, "Hierarchy error in bookmark '" + bookmark.title
- + "'. Skipping.");
- continue;
- }
- importBookmarkHierarchy(entry, results);
- }
- } else {
- sanitizeBookmarkDates(bookmark);
- ContentValues values = getBookmarkValues(bookmark);
- try {
- // Check if the URL already exists in the database.
- String[] urlArgs = new String[]{ bookmark.url };
- Uri bookmarksApiUri = ChromeBrowserProvider.getBookmarksApiUri(mContext);
- Cursor history = mContext.getContentResolver().query(
- bookmarksApiUri, null, HAS_URL, urlArgs, null);
- boolean alreadyExists = history != null && history.getCount() > 0;
- if (history != null) history.close();
-
- if (alreadyExists) {
- // If so, update the existing information.
- if (mContext.getContentResolver().update(
- bookmarksApiUri, values, HAS_URL, urlArgs) == 0) {
- throw new IllegalArgumentException(
- "Couldn't update the existing history information");
- }
- } else {
- // Otherwise insert the new information.
- if (mContext.getContentResolver().insert(
- bookmarksApiUri, values) == null) {
- throw new IllegalArgumentException(
- "Couldn't insert the bookmark");
- }
- }
- ++results.numImported;
- } catch (IllegalArgumentException e) {
- Log.w(TAG, "Error inserting bookmark " + bookmark.title + ": "
- + e.getMessage());
- }
- }
- }
-
- // Sanitize timestamp inputs as the provider backend might reject some of the bookmarks
- // if the values are inconsistent.
- private void sanitizeBookmarkDates(Bookmark bookmark) {
- final long now = System.currentTimeMillis();
- if (bookmark.created != null && bookmark.created.longValue() > now) {
- bookmark.created = Long.valueOf(now);
- }
-
- if (bookmark.lastVisit != null && bookmark.lastVisit.longValue() > now) {
- bookmark.lastVisit = Long.valueOf(now);
- }
-
- if (bookmark.created != null && bookmark.lastVisit != null
- && bookmark.created.longValue() > bookmark.lastVisit.longValue()) {
- bookmark.created = bookmark.lastVisit;
- }
-
- // The provider backend assumes one visit per timestamp and actually checks this.
- if (bookmark.lastVisit != null && bookmark.created != null && bookmark.visits != null) {
- long maxVisits = bookmark.lastVisit.longValue() - bookmark.created.longValue() + 1;
- if (bookmark.visits.longValue() > maxVisits) {
- bookmark.visits = Long.valueOf(maxVisits);
- }
- }
- }
- }
-}

Powered by Google App Engine
This is Rietveld 408576698