Backout c38e96f197e5, 7e795daed2f7, d74e5dfa1626, a942ab4e7089, 28754a456feb & d3da23241bba (bug 710330) for failures in test_localStorageOriginsDomainDiffs.html

This commit is contained in:
Ed Morley 2012-06-25 17:27:32 +01:00
parent 49ae1e0275
commit c80d69d369
12 changed files with 235 additions and 561 deletions

View File

@ -1,143 +0,0 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko;
import org.mozilla.gecko.db.BrowserContract;
import org.mozilla.gecko.db.BrowserContract.Bookmarks;
import org.mozilla.gecko.db.LocalBrowserDB;
import org.mozilla.gecko.R;
import android.content.ContentResolver;
import android.content.ContentProviderResult;
import android.content.ContentProviderOperation;
import android.content.Context;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.database.sqlite.SQLiteConstraintException;
import android.net.Uri;
import android.os.Build;
import android.os.RemoteException;
import android.preference.Preference;
import android.provider.Browser;
import android.provider.Browser.BookmarkColumns;
import android.util.Log;
import java.util.ArrayList;
import java.util.Collections;
class AndroidImport implements Runnable {
static final private String LOGTAG = "AndroidImport";
private Context mContext;
private Runnable mOnDoneRunnable;
private ArrayList<ContentProviderOperation> mOperations;
private ContentResolver mCr;
private LocalBrowserDB mDB;
private boolean mImportBookmarks;
private boolean mImportHistory;
public AndroidImport(Context context, Runnable onDoneRunnable,
boolean doBookmarks, boolean doHistory) {
mContext = context;
mOnDoneRunnable = onDoneRunnable;
mOperations = new ArrayList<ContentProviderOperation>();
mCr = mContext.getContentResolver();
mDB = new LocalBrowserDB(GeckoProfile.get(context).getName());
mImportBookmarks = doBookmarks;
mImportHistory = doHistory;
}
public void mergeBookmarks() {
Cursor cursor = mCr.query(Browser.BOOKMARKS_URI,
null,
Browser.BookmarkColumns.BOOKMARK + " = 1",
null,
null);
final int faviconCol = cursor.getColumnIndexOrThrow(Browser.BookmarkColumns.FAVICON);
final int titleCol = cursor.getColumnIndexOrThrow(Browser.BookmarkColumns.TITLE);
final int urlCol = cursor.getColumnIndexOrThrow(Browser.BookmarkColumns.URL);
// http://code.google.com/p/android/issues/detail?id=17969
final int createCol = cursor.getColumnIndex(Browser.BookmarkColumns.CREATED);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
String url = cursor.getString(urlCol);
String title = cursor.getString(titleCol);
// Need to set it to the current time so Sync picks it up.
long created = System.currentTimeMillis();
byte[] data = cursor.getBlob(faviconCol);
mDB.updateBookmarkInBatch(mCr, mOperations,
url, title, null, -1,
created, created, BrowserContract.Bookmarks.DEFAULT_POSITION,
null, Bookmarks.TYPE_BOOKMARK);
if (data != null) {
mDB.updateFaviconInBatch(mCr, mOperations, url, null, null, data);
}
cursor.moveToNext();
}
cursor.close();
flushBatchOperations();
}
public void mergeHistory() {
Cursor cursor = mCr.query(Browser.BOOKMARKS_URI,
null,
Browser.BookmarkColumns.BOOKMARK + " = 0 AND " +
Browser.BookmarkColumns.VISITS + " > 0",
null,
null);
final int dateCol = cursor.getColumnIndexOrThrow(Browser.BookmarkColumns.DATE);
final int faviconCol = cursor.getColumnIndexOrThrow(Browser.BookmarkColumns.FAVICON);
final int titleCol = cursor.getColumnIndexOrThrow(Browser.BookmarkColumns.TITLE);
final int urlCol = cursor.getColumnIndexOrThrow(Browser.BookmarkColumns.URL);
final int visitsCol = cursor.getColumnIndexOrThrow(Browser.BookmarkColumns.VISITS);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
String url = cursor.getString(urlCol);
String title = cursor.getString(titleCol);
long date = cursor.getLong(dateCol);
int visits = cursor.getInt(visitsCol);
byte[] data = cursor.getBlob(faviconCol);
mDB.updateHistoryInBatch(mCr, mOperations, url, title, date, visits);
if (data != null) {
mDB.updateFaviconInBatch(mCr, mOperations, url, null, null, data);
}
cursor.moveToNext();
}
cursor.close();
flushBatchOperations();
}
protected void flushBatchOperations() {
Log.d(LOGTAG, "Flushing " + mOperations.size() + " DB operations");
try {
// We don't really care for the results, this is best-effort.
mCr.applyBatch(BrowserContract.AUTHORITY, mOperations);
} catch (RemoteException e) {
Log.e(LOGTAG, "Remote exception while updating db: ", e);
} catch (OperationApplicationException e) {
// Bug 716729 means this happens even in normal circumstances
Log.d(LOGTAG, "Error while applying database updates: ", e);
}
mOperations.clear();
}
@Override
public void run() {
if (mImportBookmarks) {
mergeBookmarks();
}
if (mImportHistory) {
mergeHistory();
}
mOnDoneRunnable.run();
}
}

View File

@ -1,106 +0,0 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.preference.DialogPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseBooleanArray;
import org.mozilla.gecko.R;
class AndroidImportPreference extends DialogPreference {
static final private String LOGTAG = "AndroidImport";
private Context mContext;
private boolean mBookmarksChecked;
private boolean mHistoryChecked;
public AndroidImportPreference(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
}
protected void runImport(final boolean doBookmarks, final boolean doHistory) {
Log.i(LOGTAG, "Importing Android history/bookmarks");
if (!doBookmarks && !doHistory) {
return;
}
final String dialogTitle;
if (doBookmarks && doHistory) {
dialogTitle = mContext.getString(R.string.bookmarkhistory_import_both);
} else if (doBookmarks) {
dialogTitle = mContext.getString(R.string.bookmarkhistory_import_bookmarks);
} else {
dialogTitle = mContext.getString(R.string.bookmarkhistory_import_history);
}
final ProgressDialog dialog =
ProgressDialog.show(mContext,
dialogTitle,
mContext.getString(R.string.bookmarkhistory_import_wait),
true);
final Runnable stopCallback = new Runnable() {
public void run() {
GeckoApp.mAppContext.runOnUiThread(new Runnable() {
public void run() {
dialog.dismiss();
}
});
}
};
GeckoBackgroundThread.getHandler().post(
// Constructing AndroidImport may need finding the profile,
// which hits disk, so it needs to go into a Runnable too.
new Runnable() {
public void run() {
new AndroidImport(mContext, stopCallback, doBookmarks, doHistory).run();
}
}
);
}
@Override
protected void onPrepareDialogBuilder(Builder builder) {
super.onPrepareDialogBuilder(builder);
mBookmarksChecked = true;
mHistoryChecked = true;
builder.setMultiChoiceItems(R.array.pref_android_import_select,
new boolean[] { mBookmarksChecked, mHistoryChecked },
new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which,
boolean isChecked) {
Log.i(LOGTAG, "which = " + which + ", checked=" + isChecked);
if (which == 0) {
mBookmarksChecked = isChecked;
} else if (which == 1) {
mHistoryChecked = isChecked;
}
}
}
);
}
@Override
protected void onDialogClosed(boolean positiveResult) {
if (!positiveResult)
return;
runImport(mBookmarksChecked, mHistoryChecked);
}
}

View File

@ -20,7 +20,6 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
<uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"/>
<uses-permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.VIBRATE"/>

View File

@ -23,8 +23,6 @@ SYNC_PP_RES_XML=res/xml/sync_syncadapter.xml res/xml/sync_options.xml
FENNEC_JAVA_FILES = \
AboutHomeContent.java \
AboutHomeSection.java \
AndroidImport.java \
AndroidImportPreference.java \
AlertNotification.java \
AwesomeBar.java \
AwesomeBarTabs.java \

View File

@ -13,7 +13,6 @@ import org.mozilla.gecko.db.BrowserContract.Images;
import org.mozilla.gecko.db.BrowserContract.Passwords;
import org.mozilla.gecko.db.BrowserContract.URLColumns;
import org.mozilla.gecko.db.BrowserContract.SyncColumns;
import org.mozilla.gecko.db.LocalBrowserDB;
import org.mozilla.gecko.sqlite.SQLiteBridge;
import org.mozilla.gecko.sqlite.SQLiteBridgeException;
import org.mozilla.gecko.sync.setup.SyncAccounts;
@ -73,7 +72,6 @@ public class ProfileMigrator {
private Runnable mLongOperationStartCallback;
private boolean mLongOperationStartRun;
private Runnable mLongOperationStopCallback;
private LocalBrowserDB mDB;
// Default number of history entries to migrate in one run.
private static final int DEFAULT_HISTORY_MIGRATE_COUNT = 2000;
@ -711,15 +709,32 @@ public class ProfileMigrator {
public PlacesRunnable(File profileDir, int limit) {
mProfileDir = profileDir;
mMaxEntries = limit;
mDB = new LocalBrowserDB(GeckoProfile.get(mContext).getName());
}
protected Uri getBookmarksUri() {
Uri.Builder uriBuilder = Bookmarks.CONTENT_URI.buildUpon()
.appendQueryParameter(BrowserContract.PARAM_SHOW_DELETED, "1");
return uriBuilder.build();
}
protected Uri getHistoryUri() {
Uri.Builder uriBuilder = History.CONTENT_URI.buildUpon()
.appendQueryParameter(BrowserContract.PARAM_SHOW_DELETED, "1");
return uriBuilder.build();
}
protected Uri getImagesUri() {
Uri.Builder uriBuilder = Images.CONTENT_URI.buildUpon()
.appendQueryParameter(BrowserContract.PARAM_SHOW_DELETED, "1");
return uriBuilder.build();
}
private long getFolderId(String guid) {
Cursor c = null;
try {
// Uses default profile
c = mCr.query(Bookmarks.CONTENT_URI,
c = mCr.query(getBookmarksUri(),
new String[] { Bookmarks._ID },
Bookmarks.GUID + " = ?",
new String [] { guid },
@ -807,7 +822,72 @@ public class ProfileMigrator {
protected void updateBrowserHistory(String url, String title,
long date, int visits) {
mDB.updateHistoryInBatch(mCr, mOperations, url, title, date, visits);
Cursor cursor = null;
try {
final String[] projection = new String[] {
History._ID,
History.VISITS,
History.DATE_LAST_VISITED
};
cursor = mCr.query(getHistoryUri(),
projection,
History.URL + " = ?",
new String[] { url },
null);
ContentValues values = new ContentValues();
ContentProviderOperation.Builder builder = null;
// Restore deleted record if possible
values.put(History.IS_DELETED, 0);
if (cursor.moveToFirst()) {
int visitsCol = cursor.getColumnIndexOrThrow(History.VISITS);
int dateCol = cursor.getColumnIndexOrThrow(History.DATE_LAST_VISITED);
int oldVisits = cursor.getInt(visitsCol);
long oldDate = cursor.getLong(dateCol);
values.put(History.VISITS, oldVisits + visits);
if (title != null) {
values.put(History.TITLE, title);
}
// Only update last visited if newer.
if (date > oldDate) {
values.put(History.DATE_LAST_VISITED, date);
}
int idCol = cursor.getColumnIndexOrThrow(History._ID);
// We use default profile anyway
Uri historyUri = ContentUris.withAppendedId(getHistoryUri(),
cursor.getLong(idCol));
// Update
builder = ContentProviderOperation.newUpdate(historyUri);
// URL should be unique and we should hit it
builder.withExpectedCount(1);
builder.withValues(values);
} else {
values.put(History.URL, url);
values.put(History.VISITS, visits);
if (title != null) {
values.put(History.TITLE, title);
} else {
values.put(History.TITLE, url);
}
values.put(History.DATE_LAST_VISITED, date);
// Insert
builder = ContentProviderOperation.newInsert(getHistoryUri());
builder.withValues(values);
}
// Queue the operation
mOperations.add(builder.build());
} finally {
if (cursor != null)
cursor.close();
}
}
protected BitmapDrawable decodeImageData(byte[] data) {
@ -835,21 +915,57 @@ public class ProfileMigrator {
}
}
try {
byte[] newData = null;
ContentValues values = new ContentValues();
// Recompress decoded images to PNG.
if (image != null) {
Bitmap bitmap = image.getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
newData = stream.toByteArray();
values.put(Images.FAVICON, stream.toByteArray());
} else {
// PNG images can be passed directly. Well, aside
// from having to convert them into a byte[].
newData = data;
values.put(Images.FAVICON, data);
}
mDB.updateFaviconInBatch(mCr, mOperations, url, faviconUrl, faviconGuid, newData);
values.put(Images.URL, url);
values.put(Images.FAVICON_URL, faviconUrl);
// Restore deleted record if possible
values.put(Images.IS_DELETED, 0);
if (faviconGuid != null) {
values.put(Images.GUID, faviconGuid);
}
Cursor cursor = null;
ContentProviderOperation.Builder builder = null;
try {
cursor = mCr.query(getImagesUri(),
null,
Images.URL + " = ?",
new String[] { url },
null);
if (cursor != null && cursor.moveToFirst()) {
// Update
builder = ContentProviderOperation.newUpdate(getImagesUri());
// URL should be unique and we should hit it
builder.withExpectedCount(1);
builder.withValues(values);
builder.withSelection(Images.URL + " = ?",
new String[] { url });
} else {
// Insert
builder = ContentProviderOperation.newInsert(getImagesUri());
builder.withValues(values);
}
} finally {
if (cursor != null)
cursor.close();
}
// Queue the operation
mOperations.add(builder.build());
} catch (SQLException e) {
Log.i(LOGTAG, "Migrating favicon failed: " + mime + " URL: " + url
+ " error:" + e.getMessage());
@ -965,17 +1081,81 @@ public class ProfileMigrator {
long parent, long added,
long modified, long position,
String keyword, int type) {
// Translate the parent pointer if needed
ContentValues values = new ContentValues();
if (title == null && url != null) {
title = url;
}
if (title != null) {
values.put(Bookmarks.TITLE, title);
}
if (url != null) {
values.put(Bookmarks.URL, url);
}
if (guid != null) {
values.put(SyncColumns.GUID, guid);
}
if (keyword != null) {
values.put(Bookmarks.KEYWORD, keyword);
}
values.put(SyncColumns.DATE_CREATED, added);
values.put(SyncColumns.DATE_MODIFIED, modified);
values.put(Bookmarks.POSITION, position);
// Restore deleted record if possible
values.put(Bookmarks.IS_DELETED, 0);
if (mRerootMap.containsKey(parent)) {
parent = mRerootMap.get(parent);
}
values.put(Bookmarks.PARENT, parent);
// The bookmark can only be one of three valid types
int newtype = (type == PLACES_TYPE_BOOKMARK ? Bookmarks.TYPE_BOOKMARK :
type == PLACES_TYPE_FOLDER ? Bookmarks.TYPE_FOLDER :
Bookmarks.TYPE_SEPARATOR);
mDB.updateBookmarkInBatch(mCr, mOperations,
url, title, guid, parent, added,
modified, position, keyword, newtype);
values.put(Bookmarks.TYPE, type == PLACES_TYPE_BOOKMARK ? Bookmarks.TYPE_BOOKMARK :
type == PLACES_TYPE_FOLDER ? Bookmarks.TYPE_FOLDER :
Bookmarks.TYPE_SEPARATOR);
Cursor cursor = null;
ContentProviderOperation.Builder builder = null;
if (url != null) {
try {
final String[] projection = new String[] {
Bookmarks._ID,
Bookmarks.URL
};
// Check if the boomark exists
cursor = mCr.query(getBookmarksUri(),
projection,
Bookmarks.URL + " = ?",
new String[] { url },
null);
if (cursor.moveToFirst()) {
int idCol = cursor.getColumnIndexOrThrow(Bookmarks._ID);
// We use default profile anyway
Uri bookmarkUri = ContentUris.withAppendedId(getBookmarksUri(),
cursor.getLong(idCol));
// Update
builder = ContentProviderOperation.newUpdate(bookmarkUri);
// URL should be unique and we should hit it
builder.withExpectedCount(1);
builder.withValues(values);
} else {
// Insert
builder = ContentProviderOperation.newInsert(getBookmarksUri());
builder.withValues(values);
}
} finally {
if (cursor != null)
cursor.close();
}
} else {
// Insert
builder = ContentProviderOperation.newInsert(getBookmarksUri());
builder.withValues(values);
}
// Queue the operation
mOperations.add(builder.build());
}
protected void migrateBookmarks(SQLiteBridge db) {

View File

@ -96,7 +96,6 @@ public class BrowserContract {
public static final Uri PARENTS_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, "parents");
// Hacky API for bulk-updating positions. Bug 728783.
public static final Uri POSITIONS_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, "positions");
public static final long DEFAULT_POSITION = Long.MIN_VALUE;
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/bookmark";
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/bookmark";

View File

@ -1420,13 +1420,47 @@ public class BrowserProvider extends ContentProvider {
public Uri insertInTransaction(Uri uri, ContentValues values) {
trace("Calling insert in transaction on URI: " + uri);
final SQLiteDatabase db = getWritableDatabase(uri);
int match = URI_MATCHER.match(uri);
long id = -1;
switch (match) {
case BOOKMARKS: {
trace("Insert on BOOKMARKS: " + uri);
id = insertBookmark(uri, values);
// Generate values if not specified. Don't overwrite
// if specified by caller.
long now = System.currentTimeMillis();
if (!values.containsKey(Bookmarks.DATE_CREATED)) {
values.put(Bookmarks.DATE_CREATED, now);
}
if (!values.containsKey(Bookmarks.DATE_MODIFIED)) {
values.put(Bookmarks.DATE_MODIFIED, now);
}
if (!values.containsKey(Bookmarks.GUID)) {
values.put(Bookmarks.GUID, Utils.generateGuid());
}
if (!values.containsKey(Bookmarks.POSITION)) {
debug("Inserting bookmark with no position for URI");
values.put(Bookmarks.POSITION, Long.toString(Long.MIN_VALUE));
}
String url = values.getAsString(Bookmarks.URL);
ContentValues imageValues = extractImageValues(values, url);
Integer type = values.getAsInteger(Bookmarks.TYPE);
if ((type == null || type != Bookmarks.TYPE_FOLDER)
&& imageValues != null && !TextUtils.isEmpty(url)) {
debug("Inserting bookmark image for URL: " + url);
updateOrInsertImage(uri, imageValues, Images.URL + " = ?",
new String[] { url });
}
debug("Inserting bookmark in database with URL: " + url);
id = db.insertOrThrow(TABLE_BOOKMARKS, Bookmarks.TITLE, values);
break;
}
@ -1449,7 +1483,6 @@ public class BrowserProvider extends ContentProvider {
String url = values.getAsString(Images.URL);
debug("Inserting image in database with URL: " + url);
final SQLiteDatabase db = getWritableDatabase(uri);
id = db.insertOrThrow(TABLE_IMAGES, Images.URL, values);
break;
}
@ -1533,10 +1566,7 @@ public class BrowserProvider extends ContentProvider {
// fall through
case BOOKMARKS: {
debug("Updating bookmark: " + uri);
if (shouldUpdateOrInsert(uri))
updated = updateOrInsertBookmark(uri, values, selection, selectionArgs);
else
updated = updateBookmarks(uri, values, selection, selectionArgs);
updated = updateBookmarks(uri, values, selection, selectionArgs);
break;
}
@ -1564,12 +1594,8 @@ public class BrowserProvider extends ContentProvider {
if (TextUtils.isEmpty(url))
throw new IllegalArgumentException("Images.URL is required");
if (shouldUpdateOrInsert(uri))
updated = updateOrInsertImage(uri, values, Images.URL + " = ?",
new String[] { url });
else
updated = updateExistingImage(uri, values, Images.URL + " = ?",
new String[] { url });
updated = updateExistingImage(uri, values, Images.URL + " = ?",
new String[] { url });
break;
}
@ -1937,57 +1963,6 @@ public class BrowserProvider extends ContentProvider {
return getWritableDatabase(uri).update(TABLE_BOOKMARKS, values, where, selectionArgs);
}
long insertBookmark(Uri uri, ContentValues values) {
// Generate values if not specified. Don't overwrite
// if specified by caller.
long now = System.currentTimeMillis();
if (!values.containsKey(Bookmarks.DATE_CREATED)) {
values.put(Bookmarks.DATE_CREATED, now);
}
if (!values.containsKey(Bookmarks.DATE_MODIFIED)) {
values.put(Bookmarks.DATE_MODIFIED, now);
}
if (!values.containsKey(Bookmarks.GUID)) {
values.put(Bookmarks.GUID, Utils.generateGuid());
}
if (!values.containsKey(Bookmarks.POSITION)) {
debug("Inserting bookmark with no position for URI");
values.put(Bookmarks.POSITION,
Long.toString(BrowserContract.Bookmarks.DEFAULT_POSITION));
}
String url = values.getAsString(Bookmarks.URL);
ContentValues imageValues = extractImageValues(values, url);
Integer type = values.getAsInteger(Bookmarks.TYPE);
if ((type == null || type != Bookmarks.TYPE_FOLDER)
&& imageValues != null && !TextUtils.isEmpty(url)) {
debug("Inserting bookmark image for URL: " + url);
updateOrInsertImage(uri, imageValues, Images.URL + " = ?",
new String[] { url });
}
debug("Inserting bookmark in database with URL: " + url);
final SQLiteDatabase db = getWritableDatabase(uri);
return db.insertOrThrow(TABLE_BOOKMARKS, Bookmarks.TITLE, values);
}
int updateOrInsertBookmark(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int updated = updateBookmarks(uri, values, selection, selectionArgs);
if (updated > 0)
return updated;
insertBookmark(uri, values);
// Return 0 if we added a new row
return 0;
}
int updateBookmarks(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
trace("Updating bookmarks on URI: " + uri);

View File

@ -7,7 +7,6 @@ package org.mozilla.gecko.db;
import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.Collection;
import org.mozilla.gecko.db.BrowserContract.Bookmarks;
import org.mozilla.gecko.db.BrowserContract.History;
@ -15,14 +14,11 @@ import org.mozilla.gecko.db.BrowserContract.ImageColumns;
import org.mozilla.gecko.db.BrowserContract.Images;
import org.mozilla.gecko.db.BrowserContract.Combined;
import org.mozilla.gecko.db.BrowserContract.URLColumns;
import org.mozilla.gecko.db.BrowserContract.SyncColumns;
import org.mozilla.gecko.db.DBUtils;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.ContentProviderResult;
import android.content.ContentProviderOperation;
import android.database.ContentObserver;
import android.database.Cursor;
import android.database.CursorWrapper;
@ -116,24 +112,6 @@ public class LocalBrowserDB implements BrowserDB.BrowserDBIface {
return uri.buildUpon().appendQueryParameter(BrowserContract.PARAM_PROFILE, mProfile).build();
}
private Uri getAllBookmarksUri() {
Uri.Builder uriBuilder = mBookmarksUriWithProfile.buildUpon()
.appendQueryParameter(BrowserContract.PARAM_SHOW_DELETED, "1");
return uriBuilder.build();
}
private Uri getAllHistoryUri() {
Uri.Builder uriBuilder = mHistoryUriWithProfile.buildUpon()
.appendQueryParameter(BrowserContract.PARAM_SHOW_DELETED, "1");
return uriBuilder.build();
}
private Uri getAllImagesUri() {
Uri.Builder uriBuilder = mImagesUriWithProfile.buildUpon()
.appendQueryParameter(BrowserContract.PARAM_SHOW_DELETED, "1");
return uriBuilder.build();
}
private Cursor filterAllSites(ContentResolver cr, String[] projection, CharSequence constraint,
int limit, CharSequence urlFilter) {
String selection = "";
@ -680,177 +658,6 @@ public class LocalBrowserDB implements BrowserDB.BrowserDBIface {
return b;
}
// Utility function for updating existing history using batch operations
public void updateHistoryInBatch(ContentResolver cr,
Collection<ContentProviderOperation> operations,
String url, String title,
long date, int visits) {
Cursor cursor = null;
try {
final String[] projection = new String[] {
History._ID,
History.VISITS,
History.DATE_LAST_VISITED
};
// We need to get the old visit count.
cursor = cr.query(getAllHistoryUri(),
projection,
History.URL + " = ?",
new String[] { url },
null);
ContentValues values = new ContentValues();
// Restore deleted record if possible
values.put(History.IS_DELETED, 0);
if (cursor.moveToFirst()) {
int visitsCol = cursor.getColumnIndexOrThrow(History.VISITS);
int dateCol = cursor.getColumnIndexOrThrow(History.DATE_LAST_VISITED);
int oldVisits = cursor.getInt(visitsCol);
long oldDate = cursor.getLong(dateCol);
values.put(History.VISITS, oldVisits + visits);
// Only update last visited if newer.
if (date > oldDate) {
values.put(History.DATE_LAST_VISITED, date);
}
} else {
values.put(History.VISITS, 1);
values.put(History.DATE_LAST_VISITED, date);
}
if (title != null) {
values.put(History.TITLE, title);
}
values.put(History.URL, url);
Uri historyUri = getAllHistoryUri().buildUpon().
appendQueryParameter(BrowserContract.PARAM_INSERT_IF_NEEDED, "true").build();
// Update or insert
ContentProviderOperation.Builder builder =
ContentProviderOperation.newUpdate(historyUri);
builder.withSelection(History.URL + " = ?", new String[] { url });
builder.withValues(values);
// Queue the operation
operations.add(builder.build());
} finally {
if (cursor != null)
cursor.close();
}
}
public void updateBookmarkInBatch(ContentResolver cr,
Collection<ContentProviderOperation> operations,
String url, String title, String guid,
long parent, long added,
long modified, long position,
String keyword, int type) {
ContentValues values = new ContentValues();
if (title == null && url != null) {
title = url;
}
if (title != null) {
values.put(Bookmarks.TITLE, title);
}
if (url != null) {
values.put(Bookmarks.URL, url);
}
if (guid != null) {
values.put(SyncColumns.GUID, guid);
}
if (keyword != null) {
values.put(Bookmarks.KEYWORD, keyword);
}
if (added > 0) {
values.put(SyncColumns.DATE_CREATED, added);
}
if (modified > 0) {
values.put(SyncColumns.DATE_MODIFIED, modified);
}
values.put(Bookmarks.POSITION, position);
// Restore deleted record if possible
values.put(Bookmarks.IS_DELETED, 0);
// This assumes no "real" folder has a negative ID. Only
// things like the reading list folder do.
if (parent < 0) {
parent = getFolderIdFromGuid(cr, Bookmarks.MOBILE_FOLDER_GUID);
}
values.put(Bookmarks.PARENT, parent);
values.put(Bookmarks.TYPE, type);
Uri bookmarkUri = getAllBookmarksUri().buildUpon().
appendQueryParameter(BrowserContract.PARAM_INSERT_IF_NEEDED, "true").build();
// Update or insert
ContentProviderOperation.Builder builder =
ContentProviderOperation.newUpdate(bookmarkUri);
if (url != null) {
// Bookmarks are defined by their URL and Folder.
builder.withSelection(Bookmarks.URL + " = ? AND "
+ Bookmarks.PARENT + " = ? AND "
+ Bookmarks.PARENT + " != ?",
new String[] { url,
Long.toString(parent),
String.valueOf(Bookmarks.FIXED_READING_LIST_ID)
});
} else if (title != null) {
// Or their title and parent folder. (Folders!)
builder.withSelection(Bookmarks.TITLE + " = ? AND "
+ Bookmarks.PARENT + " = ? AND "
+ Bookmarks.PARENT + " != ?",
new String[] { title,
Long.toString(parent),
String.valueOf(Bookmarks.FIXED_READING_LIST_ID)
});
} else if (type == Bookmarks.TYPE_SEPARATOR) {
// Or their their position (seperators)
builder.withSelection(Bookmarks.POSITION + " = ? AND "
+ Bookmarks.PARENT + " = ? AND "
+ Bookmarks.PARENT + " != ?",
new String[] { Long.toString(position),
Long.toString(parent),
String.valueOf(Bookmarks.FIXED_READING_LIST_ID)
});
} else {
Log.e(LOGTAG, "Bookmark entry without url or title and not a seperator, not added.");
}
builder.withValues(values);
// Queue the operation
operations.add(builder.build());
}
public void updateFaviconInBatch(ContentResolver cr,
Collection<ContentProviderOperation> operations,
String url, String faviconUrl,
String faviconGuid, byte[] data) {
ContentValues values = new ContentValues();
values.put(Images.FAVICON, data);
values.put(Images.URL, url);
if (faviconUrl != null) {
values.put(Images.FAVICON_URL, faviconUrl);
}
// Restore deleted record if possible
values.put(Images.IS_DELETED, 0);
if (faviconGuid != null) {
values.put(Images.GUID, faviconGuid);
}
// Update or insert
Uri imagesUri = getAllImagesUri().buildUpon().
appendQueryParameter(BrowserContract.PARAM_INSERT_IF_NEEDED, "true").build();
// Update or insert
ContentProviderOperation.Builder builder =
ContentProviderOperation.newUpdate(imagesUri);
builder.withValues(values);
builder.withSelection(Images.URL + " = ?", new String[] { url });
// Queue the operation
operations.add(builder.build());
}
// This wrapper adds a fake "Desktop Bookmarks" folder entry to the
// beginning of the cursor's data set.
private class SpecialFoldersCursorWrapper extends CursorWrapper {

View File

@ -60,7 +60,6 @@
<!ENTITY pref_category_general "General">
<!ENTITY pref_category_privacy "Privacy &amp; Security">
<!ENTITY pref_category_content "Content">
<!ENTITY pref_category_importexport "Import &amp; Export">
<!ENTITY pref_about_firefox "About &brandShortName;">
<!ENTITY pref_do_not_track "Tell sites not to track me">
<!ENTITY pref_telemetry "Send performance data">
@ -86,7 +85,6 @@
<!ENTITY pref_use_master_password "Use master password">
<!ENTITY pref_sync "Sync">
<!ENTITY pref_search_suggestions "Show search suggestions">
<!ENTITY pref_import_android "Import from Android">
<!ENTITY quit "Quit">
@ -174,12 +172,3 @@ substitution variables. If it is difficult to translate the sense of the string
with that structure, consider a translation which ignores the preceding domain and
just addresses the organization to follow, e.g. "This site is run by " -->
<!ENTITY identity_run_by "which is run by">
<!ENTITY bookmarkhistory_button_import "Import">
<!ENTITY bookmarkhistory_import_both "Importing bookmarks and history
from Android">
<!ENTITY bookmarkhistory_import_bookmarks "Importing bookmarks
from Android">
<!ENTITY bookmarkhistory_import_history "Importing history
from Android">
<!ENTITY bookmarkhistory_import_wait "Please wait...">

View File

@ -37,8 +37,4 @@
<item>true</item>
<item>false</item>
</string-array>
<string-array name="pref_android_import_select">
<item>@string/awesomebar_bookmarks_title</item>
<item>@string/awesomebar_history_title</item>
</string-array>
</resources>

View File

@ -84,14 +84,4 @@
</PreferenceCategory>
<PreferenceCategory android:title="@string/pref_category_importexport">
<org.mozilla.gecko.AndroidImportPreference
android:title="@string/pref_import_android"
android:positiveButtonText="@string/bookmarkhistory_button_import"
android:negativeButtonText="@string/button_cancel"
android:persistent="false" />
</PreferenceCategory>
</PreferenceScreen>

View File

@ -70,7 +70,6 @@
<string name="pref_category_general">&pref_category_general;</string>
<string name="pref_category_privacy">&pref_category_privacy;</string>
<string name="pref_category_content">&pref_category_content;</string>
<string name="pref_category_importexport">&pref_category_importexport;</string>
<string name="pref_about_firefox">&pref_about_firefox;</string>
<string name="pref_do_not_track">&pref_do_not_track;</string>
<string name="pref_telemetry">&pref_telemetry;</string>
@ -95,7 +94,6 @@
<string name="pref_font_size_xlarge">&pref_font_size_xlarge;</string>
<string name="pref_sync">&pref_sync;</string>
<string name="pref_search_suggestions">&pref_search_suggestions;</string>
<string name="pref_import_android">&pref_import_android;</string>
<string name="reload">&reload;</string>
<string name="forward">&forward;</string>
@ -179,12 +177,4 @@
<!-- Site identity popup -->
<string name="identity_connected_to">&identity_connected_to;</string>
<string name="identity_run_by">&identity_run_by;</string>
<!-- Bookmark import/export -->
<string name="bookmarkhistory_button_import">&bookmarkhistory_button_import;</string>
<string name="bookmarkhistory_import_both">&bookmarkhistory_import_both;</string>
<string name="bookmarkhistory_import_bookmarks">&bookmarkhistory_import_bookmarks;</string>
<string name="bookmarkhistory_import_history">&bookmarkhistory_import_history;</string>
<string name="bookmarkhistory_import_wait">&bookmarkhistory_import_wait;</string>
</resources>