mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backout c38e96f197e5, 7e795daed2f7, d74e5dfa1626, a942ab4e7089, 28754a456feb & d3da23241bba (bug 710330) for failures in test_localStorageOriginsDomainDiffs.html
This commit is contained in:
parent
49ae1e0275
commit
c80d69d369
@ -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();
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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"/>
|
||||
|
@ -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 \
|
||||
|
@ -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) {
|
||||
|
@ -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";
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -60,7 +60,6 @@
|
||||
<!ENTITY pref_category_general "General">
|
||||
<!ENTITY pref_category_privacy "Privacy & Security">
|
||||
<!ENTITY pref_category_content "Content">
|
||||
<!ENTITY pref_category_importexport "Import & 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...">
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user