mobile/android/base/db/BrowserDatabaseHelper.java

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 package org.mozilla.gecko.db;
michael@0 7
michael@0 8 import java.io.ByteArrayOutputStream;
michael@0 9 import java.io.File;
michael@0 10 import java.lang.reflect.Field;
michael@0 11 import java.util.ArrayList;
michael@0 12 import java.util.List;
michael@0 13 import java.util.Locale;
michael@0 14 import java.util.regex.Matcher;
michael@0 15 import java.util.regex.Pattern;
michael@0 16
michael@0 17 import org.json.JSONArray;
michael@0 18 import org.json.JSONException;
michael@0 19 import org.json.JSONObject;
michael@0 20 import org.mozilla.gecko.AppConstants;
michael@0 21 import org.mozilla.gecko.Distribution;
michael@0 22 import org.mozilla.gecko.R;
michael@0 23 import org.mozilla.gecko.db.BrowserContract.Bookmarks;
michael@0 24 import org.mozilla.gecko.db.BrowserContract.Combined;
michael@0 25 import org.mozilla.gecko.db.BrowserContract.FaviconColumns;
michael@0 26 import org.mozilla.gecko.db.BrowserContract.Favicons;
michael@0 27 import org.mozilla.gecko.db.BrowserContract.History;
michael@0 28 import org.mozilla.gecko.db.BrowserContract.Obsolete;
michael@0 29 import org.mozilla.gecko.db.BrowserContract.ReadingListItems;
michael@0 30 import org.mozilla.gecko.db.BrowserContract.Thumbnails;
michael@0 31 import org.mozilla.gecko.gfx.BitmapUtils;
michael@0 32 import org.mozilla.gecko.sync.Utils;
michael@0 33 import org.mozilla.gecko.util.GeckoJarReader;
michael@0 34 import org.mozilla.gecko.util.ThreadUtils;
michael@0 35
michael@0 36 import android.content.ContentValues;
michael@0 37 import android.content.Context;
michael@0 38 import android.database.Cursor;
michael@0 39 import android.database.DatabaseUtils;
michael@0 40 import android.database.SQLException;
michael@0 41 import android.database.sqlite.SQLiteDatabase;
michael@0 42 import android.database.sqlite.SQLiteOpenHelper;
michael@0 43 import android.graphics.Bitmap;
michael@0 44 import android.net.Uri;
michael@0 45 import android.os.Build;
michael@0 46 import android.text.TextUtils;
michael@0 47 import android.util.Log;
michael@0 48
michael@0 49
michael@0 50 final class BrowserDatabaseHelper extends SQLiteOpenHelper {
michael@0 51
michael@0 52 private static final String LOGTAG = "GeckoBrowserDBHelper";
michael@0 53 public static final int DATABASE_VERSION = 18;
michael@0 54 public static final String DATABASE_NAME = "browser.db";
michael@0 55
michael@0 56 final protected Context mContext;
michael@0 57
michael@0 58 static final String TABLE_BOOKMARKS = Bookmarks.TABLE_NAME;
michael@0 59 static final String TABLE_HISTORY = History.TABLE_NAME;
michael@0 60 static final String TABLE_FAVICONS = Favicons.TABLE_NAME;
michael@0 61 static final String TABLE_THUMBNAILS = Thumbnails.TABLE_NAME;
michael@0 62 static final String TABLE_READING_LIST = ReadingListItems.TABLE_NAME;
michael@0 63
michael@0 64 static final String VIEW_COMBINED = Combined.VIEW_NAME;
michael@0 65 static final String VIEW_BOOKMARKS_WITH_FAVICONS = Bookmarks.VIEW_WITH_FAVICONS;
michael@0 66 static final String VIEW_HISTORY_WITH_FAVICONS = History.VIEW_WITH_FAVICONS;
michael@0 67 static final String VIEW_COMBINED_WITH_FAVICONS = Combined.VIEW_WITH_FAVICONS;
michael@0 68
michael@0 69 static final String TABLE_BOOKMARKS_JOIN_FAVICONS = TABLE_BOOKMARKS + " LEFT OUTER JOIN " +
michael@0 70 TABLE_FAVICONS + " ON " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.FAVICON_ID) + " = " +
michael@0 71 qualifyColumn(TABLE_FAVICONS, Favicons._ID);
michael@0 72
michael@0 73 static final String TABLE_HISTORY_JOIN_FAVICONS = TABLE_HISTORY + " LEFT OUTER JOIN " +
michael@0 74 TABLE_FAVICONS + " ON " + qualifyColumn(TABLE_HISTORY, History.FAVICON_ID) + " = " +
michael@0 75 qualifyColumn(TABLE_FAVICONS, Favicons._ID);
michael@0 76
michael@0 77 static final String TABLE_BOOKMARKS_TMP = TABLE_BOOKMARKS + "_tmp";
michael@0 78 static final String TABLE_HISTORY_TMP = TABLE_HISTORY + "_tmp";
michael@0 79 static final String TABLE_IMAGES_TMP = Obsolete.TABLE_IMAGES + "_tmp";
michael@0 80
michael@0 81 private static final String[] mobileIdColumns = new String[] { Bookmarks._ID };
michael@0 82 private static final String[] mobileIdSelectionArgs = new String[] { Bookmarks.MOBILE_FOLDER_GUID };
michael@0 83
michael@0 84 public BrowserDatabaseHelper(Context context, String databasePath) {
michael@0 85 super(context, databasePath, null, DATABASE_VERSION);
michael@0 86 mContext = context;
michael@0 87 }
michael@0 88
michael@0 89 private void createBookmarksTable(SQLiteDatabase db) {
michael@0 90 debug("Creating " + TABLE_BOOKMARKS + " table");
michael@0 91
michael@0 92 // Android versions older than Froyo ship with an sqlite
michael@0 93 // that doesn't support foreign keys.
michael@0 94 String foreignKeyOnParent = null;
michael@0 95 if (Build.VERSION.SDK_INT >= 8) {
michael@0 96 foreignKeyOnParent = ", FOREIGN KEY (" + Bookmarks.PARENT +
michael@0 97 ") REFERENCES " + TABLE_BOOKMARKS + "(" + Bookmarks._ID + ")";
michael@0 98 }
michael@0 99
michael@0 100 db.execSQL("CREATE TABLE " + TABLE_BOOKMARKS + "(" +
michael@0 101 Bookmarks._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
michael@0 102 Bookmarks.TITLE + " TEXT," +
michael@0 103 Bookmarks.URL + " TEXT," +
michael@0 104 Bookmarks.TYPE + " INTEGER NOT NULL DEFAULT " + Bookmarks.TYPE_BOOKMARK + "," +
michael@0 105 Bookmarks.PARENT + " INTEGER," +
michael@0 106 Bookmarks.POSITION + " INTEGER NOT NULL," +
michael@0 107 Bookmarks.KEYWORD + " TEXT," +
michael@0 108 Bookmarks.DESCRIPTION + " TEXT," +
michael@0 109 Bookmarks.TAGS + " TEXT," +
michael@0 110 Bookmarks.DATE_CREATED + " INTEGER," +
michael@0 111 Bookmarks.DATE_MODIFIED + " INTEGER," +
michael@0 112 Bookmarks.GUID + " TEXT NOT NULL," +
michael@0 113 Bookmarks.IS_DELETED + " INTEGER NOT NULL DEFAULT 0" +
michael@0 114 (foreignKeyOnParent != null ? foreignKeyOnParent : "") +
michael@0 115 ");");
michael@0 116
michael@0 117 db.execSQL("CREATE INDEX bookmarks_url_index ON " + TABLE_BOOKMARKS + "("
michael@0 118 + Bookmarks.URL + ")");
michael@0 119 db.execSQL("CREATE INDEX bookmarks_type_deleted_index ON " + TABLE_BOOKMARKS + "("
michael@0 120 + Bookmarks.TYPE + ", " + Bookmarks.IS_DELETED + ")");
michael@0 121 db.execSQL("CREATE UNIQUE INDEX bookmarks_guid_index ON " + TABLE_BOOKMARKS + "("
michael@0 122 + Bookmarks.GUID + ")");
michael@0 123 db.execSQL("CREATE INDEX bookmarks_modified_index ON " + TABLE_BOOKMARKS + "("
michael@0 124 + Bookmarks.DATE_MODIFIED + ")");
michael@0 125 }
michael@0 126
michael@0 127 private void createBookmarksTableOn13(SQLiteDatabase db) {
michael@0 128 debug("Creating " + TABLE_BOOKMARKS + " table");
michael@0 129
michael@0 130 // Android versions older than Froyo ship with an sqlite
michael@0 131 // that doesn't support foreign keys.
michael@0 132 String foreignKeyOnParent = null;
michael@0 133 if (Build.VERSION.SDK_INT >= 8) {
michael@0 134 foreignKeyOnParent = ", FOREIGN KEY (" + Bookmarks.PARENT +
michael@0 135 ") REFERENCES " + TABLE_BOOKMARKS + "(" + Bookmarks._ID + ")";
michael@0 136 }
michael@0 137
michael@0 138 db.execSQL("CREATE TABLE " + TABLE_BOOKMARKS + "(" +
michael@0 139 Bookmarks._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
michael@0 140 Bookmarks.TITLE + " TEXT," +
michael@0 141 Bookmarks.URL + " TEXT," +
michael@0 142 Bookmarks.TYPE + " INTEGER NOT NULL DEFAULT " + Bookmarks.TYPE_BOOKMARK + "," +
michael@0 143 Bookmarks.PARENT + " INTEGER," +
michael@0 144 Bookmarks.POSITION + " INTEGER NOT NULL," +
michael@0 145 Bookmarks.KEYWORD + " TEXT," +
michael@0 146 Bookmarks.DESCRIPTION + " TEXT," +
michael@0 147 Bookmarks.TAGS + " TEXT," +
michael@0 148 Bookmarks.FAVICON_ID + " INTEGER," +
michael@0 149 Bookmarks.DATE_CREATED + " INTEGER," +
michael@0 150 Bookmarks.DATE_MODIFIED + " INTEGER," +
michael@0 151 Bookmarks.GUID + " TEXT NOT NULL," +
michael@0 152 Bookmarks.IS_DELETED + " INTEGER NOT NULL DEFAULT 0" +
michael@0 153 (foreignKeyOnParent != null ? foreignKeyOnParent : "") +
michael@0 154 ");");
michael@0 155
michael@0 156 db.execSQL("CREATE INDEX bookmarks_url_index ON " + TABLE_BOOKMARKS + "("
michael@0 157 + Bookmarks.URL + ")");
michael@0 158 db.execSQL("CREATE INDEX bookmarks_type_deleted_index ON " + TABLE_BOOKMARKS + "("
michael@0 159 + Bookmarks.TYPE + ", " + Bookmarks.IS_DELETED + ")");
michael@0 160 db.execSQL("CREATE UNIQUE INDEX bookmarks_guid_index ON " + TABLE_BOOKMARKS + "("
michael@0 161 + Bookmarks.GUID + ")");
michael@0 162 db.execSQL("CREATE INDEX bookmarks_modified_index ON " + TABLE_BOOKMARKS + "("
michael@0 163 + Bookmarks.DATE_MODIFIED + ")");
michael@0 164 }
michael@0 165
michael@0 166 private void createHistoryTable(SQLiteDatabase db) {
michael@0 167 debug("Creating " + TABLE_HISTORY + " table");
michael@0 168 db.execSQL("CREATE TABLE " + TABLE_HISTORY + "(" +
michael@0 169 History._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
michael@0 170 History.TITLE + " TEXT," +
michael@0 171 History.URL + " TEXT NOT NULL," +
michael@0 172 History.VISITS + " INTEGER NOT NULL DEFAULT 0," +
michael@0 173 History.DATE_LAST_VISITED + " INTEGER," +
michael@0 174 History.DATE_CREATED + " INTEGER," +
michael@0 175 History.DATE_MODIFIED + " INTEGER," +
michael@0 176 History.GUID + " TEXT NOT NULL," +
michael@0 177 History.IS_DELETED + " INTEGER NOT NULL DEFAULT 0" +
michael@0 178 ");");
michael@0 179
michael@0 180 db.execSQL("CREATE INDEX history_url_index ON " + TABLE_HISTORY + "("
michael@0 181 + History.URL + ")");
michael@0 182 db.execSQL("CREATE UNIQUE INDEX history_guid_index ON " + TABLE_HISTORY + "("
michael@0 183 + History.GUID + ")");
michael@0 184 db.execSQL("CREATE INDEX history_modified_index ON " + TABLE_HISTORY + "("
michael@0 185 + History.DATE_MODIFIED + ")");
michael@0 186 db.execSQL("CREATE INDEX history_visited_index ON " + TABLE_HISTORY + "("
michael@0 187 + History.DATE_LAST_VISITED + ")");
michael@0 188 }
michael@0 189
michael@0 190 private void createHistoryTableOn13(SQLiteDatabase db) {
michael@0 191 debug("Creating " + TABLE_HISTORY + " table");
michael@0 192 db.execSQL("CREATE TABLE " + TABLE_HISTORY + "(" +
michael@0 193 History._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
michael@0 194 History.TITLE + " TEXT," +
michael@0 195 History.URL + " TEXT NOT NULL," +
michael@0 196 History.VISITS + " INTEGER NOT NULL DEFAULT 0," +
michael@0 197 History.FAVICON_ID + " INTEGER," +
michael@0 198 History.DATE_LAST_VISITED + " INTEGER," +
michael@0 199 History.DATE_CREATED + " INTEGER," +
michael@0 200 History.DATE_MODIFIED + " INTEGER," +
michael@0 201 History.GUID + " TEXT NOT NULL," +
michael@0 202 History.IS_DELETED + " INTEGER NOT NULL DEFAULT 0" +
michael@0 203 ");");
michael@0 204
michael@0 205 db.execSQL("CREATE INDEX history_url_index ON " + TABLE_HISTORY + "("
michael@0 206 + History.URL + ")");
michael@0 207 db.execSQL("CREATE UNIQUE INDEX history_guid_index ON " + TABLE_HISTORY + "("
michael@0 208 + History.GUID + ")");
michael@0 209 db.execSQL("CREATE INDEX history_modified_index ON " + TABLE_HISTORY + "("
michael@0 210 + History.DATE_MODIFIED + ")");
michael@0 211 db.execSQL("CREATE INDEX history_visited_index ON " + TABLE_HISTORY + "("
michael@0 212 + History.DATE_LAST_VISITED + ")");
michael@0 213 }
michael@0 214
michael@0 215 private void createImagesTable(SQLiteDatabase db) {
michael@0 216 debug("Creating " + Obsolete.TABLE_IMAGES + " table");
michael@0 217 db.execSQL("CREATE TABLE " + Obsolete.TABLE_IMAGES + " (" +
michael@0 218 Obsolete.Images._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
michael@0 219 Obsolete.Images.URL + " TEXT UNIQUE NOT NULL," +
michael@0 220 Obsolete.Images.FAVICON + " BLOB," +
michael@0 221 Obsolete.Images.FAVICON_URL + " TEXT," +
michael@0 222 Obsolete.Images.THUMBNAIL + " BLOB," +
michael@0 223 Obsolete.Images.DATE_CREATED + " INTEGER," +
michael@0 224 Obsolete.Images.DATE_MODIFIED + " INTEGER," +
michael@0 225 Obsolete.Images.GUID + " TEXT NOT NULL," +
michael@0 226 Obsolete.Images.IS_DELETED + " INTEGER NOT NULL DEFAULT 0" +
michael@0 227 ");");
michael@0 228
michael@0 229 db.execSQL("CREATE INDEX images_url_index ON " + Obsolete.TABLE_IMAGES + "("
michael@0 230 + Obsolete.Images.URL + ")");
michael@0 231 db.execSQL("CREATE UNIQUE INDEX images_guid_index ON " + Obsolete.TABLE_IMAGES + "("
michael@0 232 + Obsolete.Images.GUID + ")");
michael@0 233 db.execSQL("CREATE INDEX images_modified_index ON " + Obsolete.TABLE_IMAGES + "("
michael@0 234 + Obsolete.Images.DATE_MODIFIED + ")");
michael@0 235 }
michael@0 236
michael@0 237 private void createFaviconsTable(SQLiteDatabase db) {
michael@0 238 debug("Creating " + TABLE_FAVICONS + " table");
michael@0 239 db.execSQL("CREATE TABLE " + TABLE_FAVICONS + " (" +
michael@0 240 Favicons._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
michael@0 241 Favicons.URL + " TEXT UNIQUE," +
michael@0 242 Favicons.DATA + " BLOB," +
michael@0 243 Favicons.DATE_CREATED + " INTEGER," +
michael@0 244 Favicons.DATE_MODIFIED + " INTEGER" +
michael@0 245 ");");
michael@0 246
michael@0 247 db.execSQL("CREATE INDEX favicons_url_index ON " + TABLE_FAVICONS + "("
michael@0 248 + Favicons.URL + ")");
michael@0 249 db.execSQL("CREATE INDEX favicons_modified_index ON " + TABLE_FAVICONS + "("
michael@0 250 + Favicons.DATE_MODIFIED + ")");
michael@0 251 }
michael@0 252
michael@0 253 private void createThumbnailsTable(SQLiteDatabase db) {
michael@0 254 debug("Creating " + TABLE_THUMBNAILS + " table");
michael@0 255 db.execSQL("CREATE TABLE " + TABLE_THUMBNAILS + " (" +
michael@0 256 Thumbnails._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
michael@0 257 Thumbnails.URL + " TEXT UNIQUE," +
michael@0 258 Thumbnails.DATA + " BLOB" +
michael@0 259 ");");
michael@0 260
michael@0 261 db.execSQL("CREATE INDEX thumbnails_url_index ON " + TABLE_THUMBNAILS + "("
michael@0 262 + Thumbnails.URL + ")");
michael@0 263 }
michael@0 264
michael@0 265 private void createBookmarksWithImagesView(SQLiteDatabase db) {
michael@0 266 debug("Creating " + Obsolete.VIEW_BOOKMARKS_WITH_IMAGES + " view");
michael@0 267
michael@0 268 db.execSQL("CREATE VIEW IF NOT EXISTS " + Obsolete.VIEW_BOOKMARKS_WITH_IMAGES + " AS " +
michael@0 269 "SELECT " + qualifyColumn(TABLE_BOOKMARKS, "*") +
michael@0 270 ", " + Obsolete.Images.FAVICON + ", " + Obsolete.Images.THUMBNAIL + " FROM " +
michael@0 271 Obsolete.TABLE_BOOKMARKS_JOIN_IMAGES);
michael@0 272 }
michael@0 273
michael@0 274 private void createBookmarksWithFaviconsView(SQLiteDatabase db) {
michael@0 275 debug("Creating " + VIEW_BOOKMARKS_WITH_FAVICONS + " view");
michael@0 276
michael@0 277 db.execSQL("CREATE VIEW IF NOT EXISTS " + VIEW_BOOKMARKS_WITH_FAVICONS + " AS " +
michael@0 278 "SELECT " + qualifyColumn(TABLE_BOOKMARKS, "*") +
michael@0 279 ", " + qualifyColumn(TABLE_FAVICONS, Favicons.DATA) + " AS " + Bookmarks.FAVICON +
michael@0 280 ", " + qualifyColumn(TABLE_FAVICONS, Favicons.URL) + " AS " + Bookmarks.FAVICON_URL +
michael@0 281 " FROM " + TABLE_BOOKMARKS_JOIN_FAVICONS);
michael@0 282 }
michael@0 283
michael@0 284 private void createHistoryWithImagesView(SQLiteDatabase db) {
michael@0 285 debug("Creating " + Obsolete.VIEW_HISTORY_WITH_IMAGES + " view");
michael@0 286
michael@0 287 db.execSQL("CREATE VIEW IF NOT EXISTS " + Obsolete.VIEW_HISTORY_WITH_IMAGES + " AS " +
michael@0 288 "SELECT " + qualifyColumn(TABLE_HISTORY, "*") +
michael@0 289 ", " + Obsolete.Images.FAVICON + ", " + Obsolete.Images.THUMBNAIL + " FROM " +
michael@0 290 Obsolete.TABLE_HISTORY_JOIN_IMAGES);
michael@0 291 }
michael@0 292
michael@0 293 private void createHistoryWithFaviconsView(SQLiteDatabase db) {
michael@0 294 debug("Creating " + VIEW_HISTORY_WITH_FAVICONS + " view");
michael@0 295
michael@0 296 db.execSQL("CREATE VIEW IF NOT EXISTS " + VIEW_HISTORY_WITH_FAVICONS + " AS " +
michael@0 297 "SELECT " + qualifyColumn(TABLE_HISTORY, "*") +
michael@0 298 ", " + qualifyColumn(TABLE_FAVICONS, Favicons.DATA) + " AS " + History.FAVICON +
michael@0 299 ", " + qualifyColumn(TABLE_FAVICONS, Favicons.URL) + " AS " + History.FAVICON_URL +
michael@0 300 " FROM " + TABLE_HISTORY_JOIN_FAVICONS);
michael@0 301 }
michael@0 302
michael@0 303 private void createCombinedWithImagesView(SQLiteDatabase db) {
michael@0 304 debug("Creating " + Obsolete.VIEW_COMBINED_WITH_IMAGES + " view");
michael@0 305
michael@0 306 db.execSQL("CREATE VIEW IF NOT EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES + " AS" +
michael@0 307 " SELECT " + Combined.BOOKMARK_ID + ", " +
michael@0 308 Combined.HISTORY_ID + ", " +
michael@0 309 // We need to return an _id column because CursorAdapter requires it for its
michael@0 310 // default implementation for the getItemId() method. However, since
michael@0 311 // we're not using this feature in the parts of the UI using this view,
michael@0 312 // we can just use 0 for all rows.
michael@0 313 "0 AS " + Combined._ID + ", " +
michael@0 314 Combined.URL + ", " +
michael@0 315 Combined.TITLE + ", " +
michael@0 316 Combined.VISITS + ", " +
michael@0 317 Combined.DATE_LAST_VISITED + ", " +
michael@0 318 qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.FAVICON) + " AS " + Combined.FAVICON + ", " +
michael@0 319 qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.THUMBNAIL) + " AS " + Obsolete.Combined.THUMBNAIL +
michael@0 320 " FROM (" +
michael@0 321 // Bookmarks without history.
michael@0 322 " SELECT " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " AS " + Combined.BOOKMARK_ID + ", " +
michael@0 323 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " AS " + Combined.URL + ", " +
michael@0 324 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + " AS " + Combined.TITLE + ", " +
michael@0 325 "-1 AS " + Combined.HISTORY_ID + ", " +
michael@0 326 "-1 AS " + Combined.VISITS + ", " +
michael@0 327 "-1 AS " + Combined.DATE_LAST_VISITED +
michael@0 328 " FROM " + TABLE_BOOKMARKS +
michael@0 329 " WHERE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + " AND " +
michael@0 330 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " = 0 AND " +
michael@0 331 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) +
michael@0 332 " NOT IN (SELECT " + History.URL + " FROM " + TABLE_HISTORY + ")" +
michael@0 333 " UNION ALL" +
michael@0 334 // History with and without bookmark.
michael@0 335 " SELECT " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " AS " + Combined.BOOKMARK_ID + ", " +
michael@0 336 qualifyColumn(TABLE_HISTORY, History.URL) + " AS " + Combined.URL + ", " +
michael@0 337 // Prioritze bookmark titles over history titles, since the user may have
michael@0 338 // customized the title for a bookmark.
michael@0 339 "COALESCE(" + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + ", " +
michael@0 340 qualifyColumn(TABLE_HISTORY, History.TITLE) +")" + " AS " + Combined.TITLE + ", " +
michael@0 341 qualifyColumn(TABLE_HISTORY, History._ID) + " AS " + Combined.HISTORY_ID + ", " +
michael@0 342 qualifyColumn(TABLE_HISTORY, History.VISITS) + " AS " + Combined.VISITS + ", " +
michael@0 343 qualifyColumn(TABLE_HISTORY, History.DATE_LAST_VISITED) + " AS " + Combined.DATE_LAST_VISITED +
michael@0 344 " FROM " + TABLE_HISTORY + " LEFT OUTER JOIN " + TABLE_BOOKMARKS +
michael@0 345 " ON " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " = " + qualifyColumn(TABLE_HISTORY, History.URL) +
michael@0 346 " WHERE " + qualifyColumn(TABLE_HISTORY, History.URL) + " IS NOT NULL AND " +
michael@0 347 qualifyColumn(TABLE_HISTORY, History.IS_DELETED) + " = 0 AND (" +
michael@0 348 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " IS NULL OR " +
michael@0 349 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + ")" +
michael@0 350 ") LEFT OUTER JOIN " + Obsolete.TABLE_IMAGES +
michael@0 351 " ON " + Combined.URL + " = " + qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.URL));
michael@0 352 }
michael@0 353
michael@0 354 private void createCombinedWithImagesViewOn9(SQLiteDatabase db) {
michael@0 355 debug("Creating " + Obsolete.VIEW_COMBINED_WITH_IMAGES + " view");
michael@0 356
michael@0 357 db.execSQL("CREATE VIEW IF NOT EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES + " AS" +
michael@0 358 " SELECT " + Combined.BOOKMARK_ID + ", " +
michael@0 359 Combined.HISTORY_ID + ", " +
michael@0 360 // We need to return an _id column because CursorAdapter requires it for its
michael@0 361 // default implementation for the getItemId() method. However, since
michael@0 362 // we're not using this feature in the parts of the UI using this view,
michael@0 363 // we can just use 0 for all rows.
michael@0 364 "0 AS " + Combined._ID + ", " +
michael@0 365 Combined.URL + ", " +
michael@0 366 Combined.TITLE + ", " +
michael@0 367 Combined.VISITS + ", " +
michael@0 368 Combined.DISPLAY + ", " +
michael@0 369 Combined.DATE_LAST_VISITED + ", " +
michael@0 370 qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.FAVICON) + " AS " + Combined.FAVICON + ", " +
michael@0 371 qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.THUMBNAIL) + " AS " + Obsolete.Combined.THUMBNAIL +
michael@0 372 " FROM (" +
michael@0 373 // Bookmarks without history.
michael@0 374 " SELECT " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " AS " + Combined.BOOKMARK_ID + ", " +
michael@0 375 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " AS " + Combined.URL + ", " +
michael@0 376 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + " AS " + Combined.TITLE + ", " +
michael@0 377 "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " WHEN " +
michael@0 378 Bookmarks.FIXED_READING_LIST_ID + " THEN " + Combined.DISPLAY_READER + " ELSE " +
michael@0 379 Combined.DISPLAY_NORMAL + " END AS " + Combined.DISPLAY + ", " +
michael@0 380 "-1 AS " + Combined.HISTORY_ID + ", " +
michael@0 381 "-1 AS " + Combined.VISITS + ", " +
michael@0 382 "-1 AS " + Combined.DATE_LAST_VISITED +
michael@0 383 " FROM " + TABLE_BOOKMARKS +
michael@0 384 " WHERE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + " AND " +
michael@0 385 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " = 0 AND " +
michael@0 386 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) +
michael@0 387 " NOT IN (SELECT " + History.URL + " FROM " + TABLE_HISTORY + ")" +
michael@0 388 " UNION ALL" +
michael@0 389 // History with and without bookmark.
michael@0 390 " SELECT " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " AS " + Combined.BOOKMARK_ID + ", " +
michael@0 391 qualifyColumn(TABLE_HISTORY, History.URL) + " AS " + Combined.URL + ", " +
michael@0 392 // Prioritze bookmark titles over history titles, since the user may have
michael@0 393 // customized the title for a bookmark.
michael@0 394 "COALESCE(" + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + ", " +
michael@0 395 qualifyColumn(TABLE_HISTORY, History.TITLE) +")" + " AS " + Combined.TITLE + ", " +
michael@0 396 "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " WHEN " +
michael@0 397 Bookmarks.FIXED_READING_LIST_ID + " THEN " + Combined.DISPLAY_READER + " ELSE " +
michael@0 398 Combined.DISPLAY_NORMAL + " END AS " + Combined.DISPLAY + ", " +
michael@0 399 qualifyColumn(TABLE_HISTORY, History._ID) + " AS " + Combined.HISTORY_ID + ", " +
michael@0 400 qualifyColumn(TABLE_HISTORY, History.VISITS) + " AS " + Combined.VISITS + ", " +
michael@0 401 qualifyColumn(TABLE_HISTORY, History.DATE_LAST_VISITED) + " AS " + Combined.DATE_LAST_VISITED +
michael@0 402 " FROM " + TABLE_HISTORY + " LEFT OUTER JOIN " + TABLE_BOOKMARKS +
michael@0 403 " ON " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " = " + qualifyColumn(TABLE_HISTORY, History.URL) +
michael@0 404 " WHERE " + qualifyColumn(TABLE_HISTORY, History.URL) + " IS NOT NULL AND " +
michael@0 405 qualifyColumn(TABLE_HISTORY, History.IS_DELETED) + " = 0 AND (" +
michael@0 406 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " IS NULL OR " +
michael@0 407 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + ")" +
michael@0 408 ") LEFT OUTER JOIN " + Obsolete.TABLE_IMAGES +
michael@0 409 " ON " + Combined.URL + " = " + qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.URL));
michael@0 410 }
michael@0 411
michael@0 412 private void createCombinedWithImagesViewOn10(SQLiteDatabase db) {
michael@0 413 debug("Creating " + Obsolete.VIEW_COMBINED_WITH_IMAGES + " view");
michael@0 414
michael@0 415 db.execSQL("CREATE VIEW IF NOT EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES + " AS" +
michael@0 416 " SELECT " + Combined.BOOKMARK_ID + ", " +
michael@0 417 Combined.HISTORY_ID + ", " +
michael@0 418 // We need to return an _id column because CursorAdapter requires it for its
michael@0 419 // default implementation for the getItemId() method. However, since
michael@0 420 // we're not using this feature in the parts of the UI using this view,
michael@0 421 // we can just use 0 for all rows.
michael@0 422 "0 AS " + Combined._ID + ", " +
michael@0 423 Combined.URL + ", " +
michael@0 424 Combined.TITLE + ", " +
michael@0 425 Combined.VISITS + ", " +
michael@0 426 Combined.DISPLAY + ", " +
michael@0 427 Combined.DATE_LAST_VISITED + ", " +
michael@0 428 qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.FAVICON) + " AS " + Combined.FAVICON + ", " +
michael@0 429 qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.THUMBNAIL) + " AS " + Obsolete.Combined.THUMBNAIL +
michael@0 430 " FROM (" +
michael@0 431 // Bookmarks without history.
michael@0 432 " SELECT " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " AS " + Combined.BOOKMARK_ID + ", " +
michael@0 433 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " AS " + Combined.URL + ", " +
michael@0 434 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + " AS " + Combined.TITLE + ", " +
michael@0 435 "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " WHEN " +
michael@0 436 Bookmarks.FIXED_READING_LIST_ID + " THEN " + Combined.DISPLAY_READER + " ELSE " +
michael@0 437 Combined.DISPLAY_NORMAL + " END AS " + Combined.DISPLAY + ", " +
michael@0 438 "-1 AS " + Combined.HISTORY_ID + ", " +
michael@0 439 "-1 AS " + Combined.VISITS + ", " +
michael@0 440 "-1 AS " + Combined.DATE_LAST_VISITED +
michael@0 441 " FROM " + TABLE_BOOKMARKS +
michael@0 442 " WHERE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + " AND " +
michael@0 443 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " = 0 AND " +
michael@0 444 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) +
michael@0 445 " NOT IN (SELECT " + History.URL + " FROM " + TABLE_HISTORY + ")" +
michael@0 446 " UNION ALL" +
michael@0 447 // History with and without bookmark.
michael@0 448 " SELECT " + "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " WHEN 0 THEN " +
michael@0 449 qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " ELSE NULL END AS " + Combined.BOOKMARK_ID + ", " +
michael@0 450 qualifyColumn(TABLE_HISTORY, History.URL) + " AS " + Combined.URL + ", " +
michael@0 451 // Prioritze bookmark titles over history titles, since the user may have
michael@0 452 // customized the title for a bookmark.
michael@0 453 "COALESCE(" + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + ", " +
michael@0 454 qualifyColumn(TABLE_HISTORY, History.TITLE) +")" + " AS " + Combined.TITLE + ", " +
michael@0 455 "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " WHEN " +
michael@0 456 Bookmarks.FIXED_READING_LIST_ID + " THEN " + Combined.DISPLAY_READER + " ELSE " +
michael@0 457 Combined.DISPLAY_NORMAL + " END AS " + Combined.DISPLAY + ", " +
michael@0 458 qualifyColumn(TABLE_HISTORY, History._ID) + " AS " + Combined.HISTORY_ID + ", " +
michael@0 459 qualifyColumn(TABLE_HISTORY, History.VISITS) + " AS " + Combined.VISITS + ", " +
michael@0 460 qualifyColumn(TABLE_HISTORY, History.DATE_LAST_VISITED) + " AS " + Combined.DATE_LAST_VISITED +
michael@0 461 " FROM " + TABLE_HISTORY + " LEFT OUTER JOIN " + TABLE_BOOKMARKS +
michael@0 462 " ON " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " = " + qualifyColumn(TABLE_HISTORY, History.URL) +
michael@0 463 " WHERE " + qualifyColumn(TABLE_HISTORY, History.URL) + " IS NOT NULL AND " +
michael@0 464 qualifyColumn(TABLE_HISTORY, History.IS_DELETED) + " = 0 AND (" +
michael@0 465 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " IS NULL OR " +
michael@0 466 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + ")" +
michael@0 467 ") LEFT OUTER JOIN " + Obsolete.TABLE_IMAGES +
michael@0 468 " ON " + Combined.URL + " = " + qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.URL));
michael@0 469 }
michael@0 470
michael@0 471 private void createCombinedWithImagesViewOn11(SQLiteDatabase db) {
michael@0 472 debug("Creating " + Obsolete.VIEW_COMBINED_WITH_IMAGES + " view");
michael@0 473
michael@0 474 db.execSQL("CREATE VIEW IF NOT EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES + " AS" +
michael@0 475 " SELECT " + Combined.BOOKMARK_ID + ", " +
michael@0 476 Combined.HISTORY_ID + ", " +
michael@0 477 // We need to return an _id column because CursorAdapter requires it for its
michael@0 478 // default implementation for the getItemId() method. However, since
michael@0 479 // we're not using this feature in the parts of the UI using this view,
michael@0 480 // we can just use 0 for all rows.
michael@0 481 "0 AS " + Combined._ID + ", " +
michael@0 482 Combined.URL + ", " +
michael@0 483 Combined.TITLE + ", " +
michael@0 484 Combined.VISITS + ", " +
michael@0 485 Combined.DISPLAY + ", " +
michael@0 486 Combined.DATE_LAST_VISITED + ", " +
michael@0 487 qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.FAVICON) + " AS " + Combined.FAVICON + ", " +
michael@0 488 qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.THUMBNAIL) + " AS " + Obsolete.Combined.THUMBNAIL +
michael@0 489 " FROM (" +
michael@0 490 // Bookmarks without history.
michael@0 491 " SELECT " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " AS " + Combined.BOOKMARK_ID + ", " +
michael@0 492 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " AS " + Combined.URL + ", " +
michael@0 493 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + " AS " + Combined.TITLE + ", " +
michael@0 494 "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " WHEN " +
michael@0 495 Bookmarks.FIXED_READING_LIST_ID + " THEN " + Combined.DISPLAY_READER + " ELSE " +
michael@0 496 Combined.DISPLAY_NORMAL + " END AS " + Combined.DISPLAY + ", " +
michael@0 497 "-1 AS " + Combined.HISTORY_ID + ", " +
michael@0 498 "-1 AS " + Combined.VISITS + ", " +
michael@0 499 "-1 AS " + Combined.DATE_LAST_VISITED +
michael@0 500 " FROM " + TABLE_BOOKMARKS +
michael@0 501 " WHERE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + " AND " +
michael@0 502 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " = 0 AND " +
michael@0 503 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) +
michael@0 504 " NOT IN (SELECT " + History.URL + " FROM " + TABLE_HISTORY + ")" +
michael@0 505 " UNION ALL" +
michael@0 506 // History with and without bookmark.
michael@0 507 " SELECT " + "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " WHEN 0 THEN " +
michael@0 508 qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " ELSE NULL END AS " + Combined.BOOKMARK_ID + ", " +
michael@0 509 qualifyColumn(TABLE_HISTORY, History.URL) + " AS " + Combined.URL + ", " +
michael@0 510 // Prioritze bookmark titles over history titles, since the user may have
michael@0 511 // customized the title for a bookmark.
michael@0 512 "COALESCE(" + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + ", " +
michael@0 513 qualifyColumn(TABLE_HISTORY, History.TITLE) +")" + " AS " + Combined.TITLE + ", " +
michael@0 514 // Only use DISPLAY_READER if the matching bookmark entry inside reading
michael@0 515 // list folder is not marked as deleted.
michael@0 516 "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " WHEN 0 THEN CASE " +
michael@0 517 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " WHEN " + Bookmarks.FIXED_READING_LIST_ID +
michael@0 518 " THEN " + Combined.DISPLAY_READER + " ELSE " + Combined.DISPLAY_NORMAL + " END ELSE " +
michael@0 519 Combined.DISPLAY_NORMAL + " END AS " + Combined.DISPLAY + ", " +
michael@0 520 qualifyColumn(TABLE_HISTORY, History._ID) + " AS " + Combined.HISTORY_ID + ", " +
michael@0 521 qualifyColumn(TABLE_HISTORY, History.VISITS) + " AS " + Combined.VISITS + ", " +
michael@0 522 qualifyColumn(TABLE_HISTORY, History.DATE_LAST_VISITED) + " AS " + Combined.DATE_LAST_VISITED +
michael@0 523 " FROM " + TABLE_HISTORY + " LEFT OUTER JOIN " + TABLE_BOOKMARKS +
michael@0 524 " ON " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " = " + qualifyColumn(TABLE_HISTORY, History.URL) +
michael@0 525 " WHERE " + qualifyColumn(TABLE_HISTORY, History.URL) + " IS NOT NULL AND " +
michael@0 526 qualifyColumn(TABLE_HISTORY, History.IS_DELETED) + " = 0 AND (" +
michael@0 527 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " IS NULL OR " +
michael@0 528 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + ") " +
michael@0 529 ") LEFT OUTER JOIN " + Obsolete.TABLE_IMAGES +
michael@0 530 " ON " + Combined.URL + " = " + qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.URL));
michael@0 531 }
michael@0 532
michael@0 533 private void createCombinedViewOn12(SQLiteDatabase db) {
michael@0 534 debug("Creating " + VIEW_COMBINED + " view");
michael@0 535
michael@0 536 db.execSQL("CREATE VIEW IF NOT EXISTS " + VIEW_COMBINED + " AS" +
michael@0 537 " SELECT " + Combined.BOOKMARK_ID + ", " +
michael@0 538 Combined.HISTORY_ID + ", " +
michael@0 539 // We need to return an _id column because CursorAdapter requires it for its
michael@0 540 // default implementation for the getItemId() method. However, since
michael@0 541 // we're not using this feature in the parts of the UI using this view,
michael@0 542 // we can just use 0 for all rows.
michael@0 543 "0 AS " + Combined._ID + ", " +
michael@0 544 Combined.URL + ", " +
michael@0 545 Combined.TITLE + ", " +
michael@0 546 Combined.VISITS + ", " +
michael@0 547 Combined.DISPLAY + ", " +
michael@0 548 Combined.DATE_LAST_VISITED +
michael@0 549 " FROM (" +
michael@0 550 // Bookmarks without history.
michael@0 551 " SELECT " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " AS " + Combined.BOOKMARK_ID + ", " +
michael@0 552 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " AS " + Combined.URL + ", " +
michael@0 553 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + " AS " + Combined.TITLE + ", " +
michael@0 554 "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " WHEN " +
michael@0 555 Bookmarks.FIXED_READING_LIST_ID + " THEN " + Combined.DISPLAY_READER + " ELSE " +
michael@0 556 Combined.DISPLAY_NORMAL + " END AS " + Combined.DISPLAY + ", " +
michael@0 557 "-1 AS " + Combined.HISTORY_ID + ", " +
michael@0 558 "-1 AS " + Combined.VISITS + ", " +
michael@0 559 "-1 AS " + Combined.DATE_LAST_VISITED +
michael@0 560 " FROM " + TABLE_BOOKMARKS +
michael@0 561 " WHERE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + " AND " +
michael@0 562 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " = 0 AND " +
michael@0 563 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) +
michael@0 564 " NOT IN (SELECT " + History.URL + " FROM " + TABLE_HISTORY + ")" +
michael@0 565 " UNION ALL" +
michael@0 566 // History with and without bookmark.
michael@0 567 " SELECT " + "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " WHEN 0 THEN " +
michael@0 568 qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " ELSE NULL END AS " + Combined.BOOKMARK_ID + ", " +
michael@0 569 qualifyColumn(TABLE_HISTORY, History.URL) + " AS " + Combined.URL + ", " +
michael@0 570 // Prioritze bookmark titles over history titles, since the user may have
michael@0 571 // customized the title for a bookmark.
michael@0 572 "COALESCE(" + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + ", " +
michael@0 573 qualifyColumn(TABLE_HISTORY, History.TITLE) +")" + " AS " + Combined.TITLE + ", " +
michael@0 574 // Only use DISPLAY_READER if the matching bookmark entry inside reading
michael@0 575 // list folder is not marked as deleted.
michael@0 576 "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " WHEN 0 THEN CASE " +
michael@0 577 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " WHEN " + Bookmarks.FIXED_READING_LIST_ID +
michael@0 578 " THEN " + Combined.DISPLAY_READER + " ELSE " + Combined.DISPLAY_NORMAL + " END ELSE " +
michael@0 579 Combined.DISPLAY_NORMAL + " END AS " + Combined.DISPLAY + ", " +
michael@0 580 qualifyColumn(TABLE_HISTORY, History._ID) + " AS " + Combined.HISTORY_ID + ", " +
michael@0 581 qualifyColumn(TABLE_HISTORY, History.VISITS) + " AS " + Combined.VISITS + ", " +
michael@0 582 qualifyColumn(TABLE_HISTORY, History.DATE_LAST_VISITED) + " AS " + Combined.DATE_LAST_VISITED +
michael@0 583 " FROM " + TABLE_HISTORY + " LEFT OUTER JOIN " + TABLE_BOOKMARKS +
michael@0 584 " ON " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " = " + qualifyColumn(TABLE_HISTORY, History.URL) +
michael@0 585 " WHERE " + qualifyColumn(TABLE_HISTORY, History.URL) + " IS NOT NULL AND " +
michael@0 586 qualifyColumn(TABLE_HISTORY, History.IS_DELETED) + " = 0 AND (" +
michael@0 587 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " IS NULL OR " +
michael@0 588 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + ") " +
michael@0 589 ")");
michael@0 590
michael@0 591 debug("Creating " + Obsolete.VIEW_COMBINED_WITH_IMAGES + " view");
michael@0 592
michael@0 593 db.execSQL("CREATE VIEW IF NOT EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES + " AS" +
michael@0 594 " SELECT *, " +
michael@0 595 qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.FAVICON) + " AS " + Combined.FAVICON + ", " +
michael@0 596 qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.THUMBNAIL) + " AS " + Obsolete.Combined.THUMBNAIL +
michael@0 597 " FROM " + VIEW_COMBINED + " LEFT OUTER JOIN " + Obsolete.TABLE_IMAGES +
michael@0 598 " ON " + Combined.URL + " = " + qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.URL));
michael@0 599 }
michael@0 600
michael@0 601 private void createCombinedViewOn13(SQLiteDatabase db) {
michael@0 602 debug("Creating " + VIEW_COMBINED + " view");
michael@0 603
michael@0 604 db.execSQL("CREATE VIEW IF NOT EXISTS " + VIEW_COMBINED + " AS" +
michael@0 605 " SELECT " + Combined.BOOKMARK_ID + ", " +
michael@0 606 Combined.HISTORY_ID + ", " +
michael@0 607 // We need to return an _id column because CursorAdapter requires it for its
michael@0 608 // default implementation for the getItemId() method. However, since
michael@0 609 // we're not using this feature in the parts of the UI using this view,
michael@0 610 // we can just use 0 for all rows.
michael@0 611 "0 AS " + Combined._ID + ", " +
michael@0 612 Combined.URL + ", " +
michael@0 613 Combined.TITLE + ", " +
michael@0 614 Combined.VISITS + ", " +
michael@0 615 Combined.DISPLAY + ", " +
michael@0 616 Combined.DATE_LAST_VISITED + ", " +
michael@0 617 Combined.FAVICON_ID +
michael@0 618 " FROM (" +
michael@0 619 // Bookmarks without history.
michael@0 620 " SELECT " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " AS " + Combined.BOOKMARK_ID + ", " +
michael@0 621 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " AS " + Combined.URL + ", " +
michael@0 622 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + " AS " + Combined.TITLE + ", " +
michael@0 623 "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " WHEN " +
michael@0 624 Bookmarks.FIXED_READING_LIST_ID + " THEN " + Combined.DISPLAY_READER + " ELSE " +
michael@0 625 Combined.DISPLAY_NORMAL + " END AS " + Combined.DISPLAY + ", " +
michael@0 626 "-1 AS " + Combined.HISTORY_ID + ", " +
michael@0 627 "-1 AS " + Combined.VISITS + ", " +
michael@0 628 "-1 AS " + Combined.DATE_LAST_VISITED + ", " +
michael@0 629 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.FAVICON_ID) + " AS " + Combined.FAVICON_ID +
michael@0 630 " FROM " + TABLE_BOOKMARKS +
michael@0 631 " WHERE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + " AND " +
michael@0 632 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " = 0 AND " +
michael@0 633 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) +
michael@0 634 " NOT IN (SELECT " + History.URL + " FROM " + TABLE_HISTORY + ")" +
michael@0 635 " UNION ALL" +
michael@0 636 // History with and without bookmark.
michael@0 637 " SELECT " + "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " WHEN 0 THEN " +
michael@0 638 qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " ELSE NULL END AS " + Combined.BOOKMARK_ID + ", " +
michael@0 639 qualifyColumn(TABLE_HISTORY, History.URL) + " AS " + Combined.URL + ", " +
michael@0 640 // Prioritize bookmark titles over history titles, since the user may have
michael@0 641 // customized the title for a bookmark.
michael@0 642 "COALESCE(" + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + ", " +
michael@0 643 qualifyColumn(TABLE_HISTORY, History.TITLE) +")" + " AS " + Combined.TITLE + ", " +
michael@0 644 // Only use DISPLAY_READER if the matching bookmark entry inside reading
michael@0 645 // list folder is not marked as deleted.
michael@0 646 "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " WHEN 0 THEN CASE " +
michael@0 647 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " WHEN " + Bookmarks.FIXED_READING_LIST_ID +
michael@0 648 " THEN " + Combined.DISPLAY_READER + " ELSE " + Combined.DISPLAY_NORMAL + " END ELSE " +
michael@0 649 Combined.DISPLAY_NORMAL + " END AS " + Combined.DISPLAY + ", " +
michael@0 650 qualifyColumn(TABLE_HISTORY, History._ID) + " AS " + Combined.HISTORY_ID + ", " +
michael@0 651 qualifyColumn(TABLE_HISTORY, History.VISITS) + " AS " + Combined.VISITS + ", " +
michael@0 652 qualifyColumn(TABLE_HISTORY, History.DATE_LAST_VISITED) + " AS " + Combined.DATE_LAST_VISITED + ", " +
michael@0 653 qualifyColumn(TABLE_HISTORY, History.FAVICON_ID) + " AS " + Combined.FAVICON_ID +
michael@0 654 " FROM " + TABLE_HISTORY + " LEFT OUTER JOIN " + TABLE_BOOKMARKS +
michael@0 655 " ON " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " = " + qualifyColumn(TABLE_HISTORY, History.URL) +
michael@0 656 " WHERE " + qualifyColumn(TABLE_HISTORY, History.URL) + " IS NOT NULL AND " +
michael@0 657 qualifyColumn(TABLE_HISTORY, History.IS_DELETED) + " = 0 AND (" +
michael@0 658 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " IS NULL OR " +
michael@0 659 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + ") " +
michael@0 660 ")");
michael@0 661
michael@0 662 debug("Creating " + VIEW_COMBINED_WITH_FAVICONS + " view");
michael@0 663
michael@0 664 db.execSQL("CREATE VIEW IF NOT EXISTS " + VIEW_COMBINED_WITH_FAVICONS + " AS" +
michael@0 665 " SELECT " + qualifyColumn(VIEW_COMBINED, "*") + ", " +
michael@0 666 qualifyColumn(TABLE_FAVICONS, Favicons.URL) + " AS " + Combined.FAVICON_URL + ", " +
michael@0 667 qualifyColumn(TABLE_FAVICONS, Favicons.DATA) + " AS " + Combined.FAVICON +
michael@0 668 " FROM " + VIEW_COMBINED + " LEFT OUTER JOIN " + TABLE_FAVICONS +
michael@0 669 " ON " + Combined.FAVICON_ID + " = " + qualifyColumn(TABLE_FAVICONS, Favicons._ID));
michael@0 670 }
michael@0 671
michael@0 672 private void createCombinedViewOn16(SQLiteDatabase db) {
michael@0 673 debug("Creating " + VIEW_COMBINED + " view");
michael@0 674
michael@0 675 db.execSQL("CREATE VIEW IF NOT EXISTS " + VIEW_COMBINED + " AS" +
michael@0 676 " SELECT " + Combined.BOOKMARK_ID + ", " +
michael@0 677 Combined.HISTORY_ID + ", " +
michael@0 678 // We need to return an _id column because CursorAdapter requires it for its
michael@0 679 // default implementation for the getItemId() method. However, since
michael@0 680 // we're not using this feature in the parts of the UI using this view,
michael@0 681 // we can just use 0 for all rows.
michael@0 682 "0 AS " + Combined._ID + ", " +
michael@0 683 Combined.URL + ", " +
michael@0 684 Combined.TITLE + ", " +
michael@0 685 Combined.VISITS + ", " +
michael@0 686 Combined.DISPLAY + ", " +
michael@0 687 Combined.DATE_LAST_VISITED + ", " +
michael@0 688 Combined.FAVICON_ID +
michael@0 689 " FROM (" +
michael@0 690 // Bookmarks without history.
michael@0 691 " SELECT " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " AS " + Combined.BOOKMARK_ID + ", " +
michael@0 692 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " AS " + Combined.URL + ", " +
michael@0 693 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + " AS " + Combined.TITLE + ", " +
michael@0 694 "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " WHEN " +
michael@0 695 Bookmarks.FIXED_READING_LIST_ID + " THEN " + Combined.DISPLAY_READER + " ELSE " +
michael@0 696 Combined.DISPLAY_NORMAL + " END AS " + Combined.DISPLAY + ", " +
michael@0 697 "-1 AS " + Combined.HISTORY_ID + ", " +
michael@0 698 "-1 AS " + Combined.VISITS + ", " +
michael@0 699 "-1 AS " + Combined.DATE_LAST_VISITED + ", " +
michael@0 700 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.FAVICON_ID) + " AS " + Combined.FAVICON_ID +
michael@0 701 " FROM " + TABLE_BOOKMARKS +
michael@0 702 " WHERE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + " AND " +
michael@0 703 // Ignore pinned bookmarks.
michael@0 704 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " <> " + Bookmarks.FIXED_PINNED_LIST_ID + " AND " +
michael@0 705 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " = 0 AND " +
michael@0 706 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) +
michael@0 707 " NOT IN (SELECT " + History.URL + " FROM " + TABLE_HISTORY + ")" +
michael@0 708 " UNION ALL" +
michael@0 709 // History with and without bookmark.
michael@0 710 " SELECT " + "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " WHEN 0 THEN " +
michael@0 711 // Give pinned bookmarks a NULL ID so that they're not treated as bookmarks. We can't
michael@0 712 // completely ignore them here because they're joined with history entries we care about.
michael@0 713 "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " WHEN " +
michael@0 714 Bookmarks.FIXED_PINNED_LIST_ID + " THEN NULL ELSE " +
michael@0 715 qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " END " +
michael@0 716 "ELSE NULL END AS " + Combined.BOOKMARK_ID + ", " +
michael@0 717 qualifyColumn(TABLE_HISTORY, History.URL) + " AS " + Combined.URL + ", " +
michael@0 718 // Prioritize bookmark titles over history titles, since the user may have
michael@0 719 // customized the title for a bookmark.
michael@0 720 "COALESCE(" + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + ", " +
michael@0 721 qualifyColumn(TABLE_HISTORY, History.TITLE) +")" + " AS " + Combined.TITLE + ", " +
michael@0 722 // Only use DISPLAY_READER if the matching bookmark entry inside reading
michael@0 723 // list folder is not marked as deleted.
michael@0 724 "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " WHEN 0 THEN CASE " +
michael@0 725 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " WHEN " + Bookmarks.FIXED_READING_LIST_ID +
michael@0 726 " THEN " + Combined.DISPLAY_READER + " ELSE " + Combined.DISPLAY_NORMAL + " END ELSE " +
michael@0 727 Combined.DISPLAY_NORMAL + " END AS " + Combined.DISPLAY + ", " +
michael@0 728 qualifyColumn(TABLE_HISTORY, History._ID) + " AS " + Combined.HISTORY_ID + ", " +
michael@0 729 qualifyColumn(TABLE_HISTORY, History.VISITS) + " AS " + Combined.VISITS + ", " +
michael@0 730 qualifyColumn(TABLE_HISTORY, History.DATE_LAST_VISITED) + " AS " + Combined.DATE_LAST_VISITED + ", " +
michael@0 731 qualifyColumn(TABLE_HISTORY, History.FAVICON_ID) + " AS " + Combined.FAVICON_ID +
michael@0 732 " FROM " + TABLE_HISTORY + " LEFT OUTER JOIN " + TABLE_BOOKMARKS +
michael@0 733 " ON " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " = " + qualifyColumn(TABLE_HISTORY, History.URL) +
michael@0 734 " WHERE " + qualifyColumn(TABLE_HISTORY, History.URL) + " IS NOT NULL AND " +
michael@0 735 qualifyColumn(TABLE_HISTORY, History.IS_DELETED) + " = 0 AND (" +
michael@0 736 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " IS NULL OR " +
michael@0 737 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + ") " +
michael@0 738 ")");
michael@0 739
michael@0 740 debug("Creating " + VIEW_COMBINED_WITH_FAVICONS + " view");
michael@0 741
michael@0 742 db.execSQL("CREATE VIEW IF NOT EXISTS " + VIEW_COMBINED_WITH_FAVICONS + " AS" +
michael@0 743 " SELECT " + qualifyColumn(VIEW_COMBINED, "*") + ", " +
michael@0 744 qualifyColumn(TABLE_FAVICONS, Favicons.URL) + " AS " + Combined.FAVICON_URL + ", " +
michael@0 745 qualifyColumn(TABLE_FAVICONS, Favicons.DATA) + " AS " + Combined.FAVICON +
michael@0 746 " FROM " + VIEW_COMBINED + " LEFT OUTER JOIN " + TABLE_FAVICONS +
michael@0 747 " ON " + Combined.FAVICON_ID + " = " + qualifyColumn(TABLE_FAVICONS, Favicons._ID));
michael@0 748 }
michael@0 749
michael@0 750 @Override
michael@0 751 public void onCreate(SQLiteDatabase db) {
michael@0 752 debug("Creating browser.db: " + db.getPath());
michael@0 753
michael@0 754 createBookmarksTableOn13(db);
michael@0 755 createHistoryTableOn13(db);
michael@0 756 createFaviconsTable(db);
michael@0 757 createThumbnailsTable(db);
michael@0 758
michael@0 759 createBookmarksWithFaviconsView(db);
michael@0 760 createHistoryWithFaviconsView(db);
michael@0 761 createCombinedViewOn16(db);
michael@0 762
michael@0 763 createOrUpdateSpecialFolder(db, Bookmarks.PLACES_FOLDER_GUID,
michael@0 764 R.string.bookmarks_folder_places, 0);
michael@0 765
michael@0 766 createOrUpdateAllSpecialFolders(db);
michael@0 767
michael@0 768 // Create distribution bookmarks before our own default bookmarks
michael@0 769 int pos = createDistributionBookmarks(db);
michael@0 770 createDefaultBookmarks(db, pos);
michael@0 771
michael@0 772 createReadingListTable(db);
michael@0 773 }
michael@0 774
michael@0 775 private String getLocalizedProperty(JSONObject bookmark, String property, Locale locale) throws JSONException {
michael@0 776 // Try the full locale
michael@0 777 String fullLocale = property + "." + locale.toString();
michael@0 778 if (bookmark.has(fullLocale)) {
michael@0 779 return bookmark.getString(fullLocale);
michael@0 780 }
michael@0 781 // Try without a variant
michael@0 782 if (!TextUtils.isEmpty(locale.getVariant())) {
michael@0 783 String noVariant = fullLocale.substring(0, fullLocale.lastIndexOf("_"));
michael@0 784 if (bookmark.has(noVariant)) {
michael@0 785 return bookmark.getString(noVariant);
michael@0 786 }
michael@0 787 }
michael@0 788 // Try just the language
michael@0 789 String lang = property + "." + locale.getLanguage();
michael@0 790 if (bookmark.has(lang)) {
michael@0 791 return bookmark.getString(lang);
michael@0 792 }
michael@0 793 // Default to the non-localized property name
michael@0 794 return bookmark.getString(property);
michael@0 795 }
michael@0 796
michael@0 797 // Returns the number of bookmarks inserted in the db
michael@0 798 private int createDistributionBookmarks(SQLiteDatabase db) {
michael@0 799 JSONArray bookmarks = Distribution.getBookmarks(mContext);
michael@0 800 if (bookmarks == null) {
michael@0 801 return 0;
michael@0 802 }
michael@0 803
michael@0 804 Locale locale = Locale.getDefault();
michael@0 805 int pos = 0;
michael@0 806 Integer mobileFolderId = getMobileFolderId(db);
michael@0 807 if (mobileFolderId == null) {
michael@0 808 Log.e(LOGTAG, "Error creating distribution bookmarks: mobileFolderId is null");
michael@0 809 return 0;
michael@0 810 }
michael@0 811
michael@0 812 for (int i = 0; i < bookmarks.length(); i++) {
michael@0 813 try {
michael@0 814 final JSONObject bookmark = bookmarks.getJSONObject(i);
michael@0 815
michael@0 816 String title = getLocalizedProperty(bookmark, "title", locale);
michael@0 817 final String url = getLocalizedProperty(bookmark, "url", locale);
michael@0 818 createBookmark(db, title, url, pos, mobileFolderId);
michael@0 819
michael@0 820 if (bookmark.has("pinned")) {
michael@0 821 try {
michael@0 822 // Create a fake bookmark in the hidden pinned folder to pin bookmark
michael@0 823 // to about:home top sites. Pass pos as the pinned position to pin
michael@0 824 // sites in the order that bookmarks are specified in bookmarks.json.
michael@0 825 if (bookmark.getBoolean("pinned")) {
michael@0 826 createBookmark(db, title, url, pos, Bookmarks.FIXED_PINNED_LIST_ID);
michael@0 827 }
michael@0 828 } catch (JSONException e) {
michael@0 829 Log.e(LOGTAG, "Error pinning bookmark to top sites", e);
michael@0 830 }
michael@0 831 }
michael@0 832
michael@0 833 pos++;
michael@0 834
michael@0 835 // return early if there is no icon for this bookmark
michael@0 836 if (!bookmark.has("icon")) {
michael@0 837 continue;
michael@0 838 }
michael@0 839
michael@0 840 // create icons in a separate thread to avoid blocking about:home on startup
michael@0 841 ThreadUtils.postToBackgroundThread(new Runnable() {
michael@0 842 @Override
michael@0 843 public void run() {
michael@0 844 SQLiteDatabase db = getWritableDatabase();
michael@0 845 try {
michael@0 846 String iconData = bookmark.getString("icon");
michael@0 847 Bitmap icon = BitmapUtils.getBitmapFromDataURI(iconData);
michael@0 848 if (icon != null) {
michael@0 849 createFavicon(db, url, icon);
michael@0 850 }
michael@0 851 } catch (JSONException e) {
michael@0 852 Log.e(LOGTAG, "Error creating distribution bookmark icon", e);
michael@0 853 }
michael@0 854 }
michael@0 855 });
michael@0 856 } catch (JSONException e) {
michael@0 857 Log.e(LOGTAG, "Error creating distribution bookmark", e);
michael@0 858 }
michael@0 859 }
michael@0 860 return pos;
michael@0 861 }
michael@0 862
michael@0 863 private void createReadingListTable(SQLiteDatabase db) {
michael@0 864 debug("Creating " + TABLE_READING_LIST + " table");
michael@0 865
michael@0 866 db.execSQL("CREATE TABLE " + TABLE_READING_LIST + "(" +
michael@0 867 ReadingListItems._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
michael@0 868 ReadingListItems.URL + " TEXT NOT NULL, " +
michael@0 869 ReadingListItems.TITLE + " TEXT, " +
michael@0 870 ReadingListItems.EXCERPT + " TEXT, " +
michael@0 871 ReadingListItems.READ + " TINYINT DEFAULT 0, " +
michael@0 872 ReadingListItems.IS_DELETED + " TINYINT DEFAULT 0, " +
michael@0 873 ReadingListItems.GUID + " TEXT UNIQUE NOT NULL, " +
michael@0 874 ReadingListItems.DATE_MODIFIED + " INTEGER NOT NULL, " +
michael@0 875 ReadingListItems.DATE_CREATED + " INTEGER NOT NULL, " +
michael@0 876 ReadingListItems.LENGTH + " INTEGER DEFAULT 0 ); ");
michael@0 877
michael@0 878 db.execSQL("CREATE INDEX reading_list_url ON " + TABLE_READING_LIST + "("
michael@0 879 + ReadingListItems.URL + ")");
michael@0 880 db.execSQL("CREATE UNIQUE INDEX reading_list_guid ON " + TABLE_READING_LIST + "("
michael@0 881 + ReadingListItems.GUID + ")");
michael@0 882 }
michael@0 883
michael@0 884 // Inserts default bookmarks, starting at a specified position
michael@0 885 private void createDefaultBookmarks(SQLiteDatabase db, int pos) {
michael@0 886 Class<?> stringsClass = R.string.class;
michael@0 887 Field[] fields = stringsClass.getFields();
michael@0 888 Pattern p = Pattern.compile("^bookmarkdefaults_title_");
michael@0 889
michael@0 890 Integer mobileFolderId = getMobileFolderId(db);
michael@0 891 if (mobileFolderId == null) {
michael@0 892 Log.e(LOGTAG, "Error creating default bookmarks: mobileFolderId is null");
michael@0 893 return;
michael@0 894 }
michael@0 895
michael@0 896 for (int i = 0; i < fields.length; i++) {
michael@0 897 final String name = fields[i].getName();
michael@0 898 Matcher m = p.matcher(name);
michael@0 899 if (!m.find()) {
michael@0 900 continue;
michael@0 901 }
michael@0 902 try {
michael@0 903 int titleid = fields[i].getInt(null);
michael@0 904 String title = mContext.getString(titleid);
michael@0 905
michael@0 906 Field urlField = stringsClass.getField(name.replace("_title_", "_url_"));
michael@0 907 int urlId = urlField.getInt(null);
michael@0 908 final String url = mContext.getString(urlId);
michael@0 909 createBookmark(db, title, url, pos, mobileFolderId);
michael@0 910
michael@0 911 // create icons in a separate thread to avoid blocking about:home on startup
michael@0 912 ThreadUtils.postToBackgroundThread(new Runnable() {
michael@0 913 @Override
michael@0 914 public void run() {
michael@0 915 SQLiteDatabase db = getWritableDatabase();
michael@0 916 Bitmap icon = getDefaultFaviconFromPath(name);
michael@0 917 if (icon == null) {
michael@0 918 icon = getDefaultFaviconFromDrawable(name);
michael@0 919 }
michael@0 920 if (icon != null) {
michael@0 921 createFavicon(db, url, icon);
michael@0 922 }
michael@0 923 }
michael@0 924 });
michael@0 925 pos++;
michael@0 926 } catch (java.lang.IllegalAccessException ex) {
michael@0 927 Log.e(LOGTAG, "Can't create bookmark " + name, ex);
michael@0 928 } catch (java.lang.NoSuchFieldException ex) {
michael@0 929 Log.e(LOGTAG, "Can't create bookmark " + name, ex);
michael@0 930 }
michael@0 931 }
michael@0 932 }
michael@0 933
michael@0 934 private void createBookmark(SQLiteDatabase db, String title, String url, int pos, int parent) {
michael@0 935 ContentValues bookmarkValues = new ContentValues();
michael@0 936 bookmarkValues.put(Bookmarks.PARENT, parent);
michael@0 937
michael@0 938 long now = System.currentTimeMillis();
michael@0 939 bookmarkValues.put(Bookmarks.DATE_CREATED, now);
michael@0 940 bookmarkValues.put(Bookmarks.DATE_MODIFIED, now);
michael@0 941
michael@0 942 bookmarkValues.put(Bookmarks.TITLE, title);
michael@0 943 bookmarkValues.put(Bookmarks.URL, url);
michael@0 944 bookmarkValues.put(Bookmarks.GUID, Utils.generateGuid());
michael@0 945 bookmarkValues.put(Bookmarks.POSITION, pos);
michael@0 946 db.insertOrThrow(TABLE_BOOKMARKS, Bookmarks.TITLE, bookmarkValues);
michael@0 947 }
michael@0 948
michael@0 949 private void createFavicon(SQLiteDatabase db, String url, Bitmap icon) {
michael@0 950 ByteArrayOutputStream stream = new ByteArrayOutputStream();
michael@0 951
michael@0 952 ContentValues iconValues = new ContentValues();
michael@0 953 iconValues.put(Favicons.PAGE_URL, url);
michael@0 954
michael@0 955 byte[] data = null;
michael@0 956 if (icon.compress(Bitmap.CompressFormat.PNG, 100, stream)) {
michael@0 957 data = stream.toByteArray();
michael@0 958 } else {
michael@0 959 Log.w(LOGTAG, "Favicon compression failed.");
michael@0 960 }
michael@0 961 iconValues.put(Favicons.DATA, data);
michael@0 962
michael@0 963 insertFavicon(db, iconValues);
michael@0 964 }
michael@0 965
michael@0 966 private Bitmap getDefaultFaviconFromPath(String name) {
michael@0 967 Class<?> stringClass = R.string.class;
michael@0 968 try {
michael@0 969 // Look for a drawable with the id R.drawable.bookmarkdefaults_favicon_*
michael@0 970 Field faviconField = stringClass.getField(name.replace("_title_", "_favicon_"));
michael@0 971 if (faviconField == null) {
michael@0 972 return null;
michael@0 973 }
michael@0 974 int faviconId = faviconField.getInt(null);
michael@0 975 String path = mContext.getString(faviconId);
michael@0 976
michael@0 977 String apkPath = mContext.getPackageResourcePath();
michael@0 978 File apkFile = new File(apkPath);
michael@0 979 String bitmapPath = "jar:jar:" + apkFile.toURI() + "!/" + AppConstants.OMNIJAR_NAME + "!/" + path;
michael@0 980 return GeckoJarReader.getBitmap(mContext.getResources(), bitmapPath);
michael@0 981 } catch (java.lang.IllegalAccessException ex) {
michael@0 982 Log.e(LOGTAG, "[Path] Can't create favicon " + name, ex);
michael@0 983 } catch (java.lang.NoSuchFieldException ex) {
michael@0 984 // If the field does not exist, that means we intend to load via a drawable
michael@0 985 }
michael@0 986 return null;
michael@0 987 }
michael@0 988
michael@0 989 private Bitmap getDefaultFaviconFromDrawable(String name) {
michael@0 990 Class<?> drawablesClass = R.drawable.class;
michael@0 991 try {
michael@0 992 // Look for a drawable with the id R.drawable.bookmarkdefaults_favicon_*
michael@0 993 Field faviconField = drawablesClass.getField(name.replace("_title_", "_favicon_"));
michael@0 994 if (faviconField == null) {
michael@0 995 return null;
michael@0 996 }
michael@0 997 int faviconId = faviconField.getInt(null);
michael@0 998 return BitmapUtils.decodeResource(mContext, faviconId);
michael@0 999 } catch (java.lang.IllegalAccessException ex) {
michael@0 1000 Log.e(LOGTAG, "[Drawable] Can't create favicon " + name, ex);
michael@0 1001 } catch (java.lang.NoSuchFieldException ex) {
michael@0 1002 // If the field does not exist, that means we intend to load via a file path
michael@0 1003 }
michael@0 1004 return null;
michael@0 1005 }
michael@0 1006
michael@0 1007 private void createOrUpdateAllSpecialFolders(SQLiteDatabase db) {
michael@0 1008 createOrUpdateSpecialFolder(db, Bookmarks.MOBILE_FOLDER_GUID,
michael@0 1009 R.string.bookmarks_folder_mobile, 0);
michael@0 1010 createOrUpdateSpecialFolder(db, Bookmarks.TOOLBAR_FOLDER_GUID,
michael@0 1011 R.string.bookmarks_folder_toolbar, 1);
michael@0 1012 createOrUpdateSpecialFolder(db, Bookmarks.MENU_FOLDER_GUID,
michael@0 1013 R.string.bookmarks_folder_menu, 2);
michael@0 1014 createOrUpdateSpecialFolder(db, Bookmarks.TAGS_FOLDER_GUID,
michael@0 1015 R.string.bookmarks_folder_tags, 3);
michael@0 1016 createOrUpdateSpecialFolder(db, Bookmarks.UNFILED_FOLDER_GUID,
michael@0 1017 R.string.bookmarks_folder_unfiled, 4);
michael@0 1018 createOrUpdateSpecialFolder(db, Bookmarks.READING_LIST_FOLDER_GUID,
michael@0 1019 R.string.bookmarks_folder_reading_list, 5);
michael@0 1020 createOrUpdateSpecialFolder(db, Bookmarks.PINNED_FOLDER_GUID,
michael@0 1021 R.string.bookmarks_folder_pinned, 6);
michael@0 1022 }
michael@0 1023
michael@0 1024 private void createOrUpdateSpecialFolder(SQLiteDatabase db,
michael@0 1025 String guid, int titleId, int position) {
michael@0 1026 ContentValues values = new ContentValues();
michael@0 1027 values.put(Bookmarks.GUID, guid);
michael@0 1028 values.put(Bookmarks.TYPE, Bookmarks.TYPE_FOLDER);
michael@0 1029 values.put(Bookmarks.POSITION, position);
michael@0 1030
michael@0 1031 if (guid.equals(Bookmarks.PLACES_FOLDER_GUID))
michael@0 1032 values.put(Bookmarks._ID, Bookmarks.FIXED_ROOT_ID);
michael@0 1033 else if (guid.equals(Bookmarks.READING_LIST_FOLDER_GUID))
michael@0 1034 values.put(Bookmarks._ID, Bookmarks.FIXED_READING_LIST_ID);
michael@0 1035 else if (guid.equals(Bookmarks.PINNED_FOLDER_GUID))
michael@0 1036 values.put(Bookmarks._ID, Bookmarks.FIXED_PINNED_LIST_ID);
michael@0 1037
michael@0 1038 // Set the parent to 0, which sync assumes is the root
michael@0 1039 values.put(Bookmarks.PARENT, Bookmarks.FIXED_ROOT_ID);
michael@0 1040
michael@0 1041 String title = mContext.getResources().getString(titleId);
michael@0 1042 values.put(Bookmarks.TITLE, title);
michael@0 1043
michael@0 1044 long now = System.currentTimeMillis();
michael@0 1045 values.put(Bookmarks.DATE_CREATED, now);
michael@0 1046 values.put(Bookmarks.DATE_MODIFIED, now);
michael@0 1047
michael@0 1048 int updated = db.update(TABLE_BOOKMARKS, values,
michael@0 1049 Bookmarks.GUID + " = ?",
michael@0 1050 new String[] { guid });
michael@0 1051
michael@0 1052 if (updated == 0) {
michael@0 1053 db.insert(TABLE_BOOKMARKS, Bookmarks.GUID, values);
michael@0 1054 debug("Inserted special folder: " + guid);
michael@0 1055 } else {
michael@0 1056 debug("Updated special folder: " + guid);
michael@0 1057 }
michael@0 1058 }
michael@0 1059
michael@0 1060 private boolean isSpecialFolder(ContentValues values) {
michael@0 1061 String guid = values.getAsString(Bookmarks.GUID);
michael@0 1062 if (guid == null)
michael@0 1063 return false;
michael@0 1064
michael@0 1065 return guid.equals(Bookmarks.MOBILE_FOLDER_GUID) ||
michael@0 1066 guid.equals(Bookmarks.MENU_FOLDER_GUID) ||
michael@0 1067 guid.equals(Bookmarks.TOOLBAR_FOLDER_GUID) ||
michael@0 1068 guid.equals(Bookmarks.UNFILED_FOLDER_GUID) ||
michael@0 1069 guid.equals(Bookmarks.TAGS_FOLDER_GUID);
michael@0 1070 }
michael@0 1071
michael@0 1072 private void migrateBookmarkFolder(SQLiteDatabase db, int folderId,
michael@0 1073 BookmarkMigrator migrator) {
michael@0 1074 Cursor c = null;
michael@0 1075
michael@0 1076 debug("Migrating bookmark folder with id = " + folderId);
michael@0 1077
michael@0 1078 String selection = Bookmarks.PARENT + " = " + folderId;
michael@0 1079 String[] selectionArgs = null;
michael@0 1080
michael@0 1081 boolean isRootFolder = (folderId == Bookmarks.FIXED_ROOT_ID);
michael@0 1082
michael@0 1083 // If we're loading the root folder, we have to account for
michael@0 1084 // any previously created special folder that was created without
michael@0 1085 // setting a parent id (e.g. mobile folder) and making sure we're
michael@0 1086 // not adding any infinite recursion as root's parent is root itself.
michael@0 1087 if (isRootFolder) {
michael@0 1088 selection = Bookmarks.GUID + " != ?" + " AND (" +
michael@0 1089 selection + " OR " + Bookmarks.PARENT + " = NULL)";
michael@0 1090 selectionArgs = new String[] { Bookmarks.PLACES_FOLDER_GUID };
michael@0 1091 }
michael@0 1092
michael@0 1093 List<Integer> subFolders = new ArrayList<Integer>();
michael@0 1094 List<ContentValues> invalidSpecialEntries = new ArrayList<ContentValues>();
michael@0 1095
michael@0 1096 try {
michael@0 1097 c = db.query(TABLE_BOOKMARKS_TMP,
michael@0 1098 null,
michael@0 1099 selection,
michael@0 1100 selectionArgs,
michael@0 1101 null, null, null);
michael@0 1102
michael@0 1103 // The key point here is that bookmarks should be added in
michael@0 1104 // parent order to avoid any problems with the foreign key
michael@0 1105 // in Bookmarks.PARENT.
michael@0 1106 while (c.moveToNext()) {
michael@0 1107 ContentValues values = new ContentValues();
michael@0 1108
michael@0 1109 // We're using a null projection in the query which
michael@0 1110 // means we're getting all columns from the table.
michael@0 1111 // It's safe to simply transform the row into the
michael@0 1112 // values to be inserted on the new table.
michael@0 1113 DatabaseUtils.cursorRowToContentValues(c, values);
michael@0 1114
michael@0 1115 boolean isSpecialFolder = isSpecialFolder(values);
michael@0 1116
michael@0 1117 // The mobile folder used to be created with PARENT = NULL.
michael@0 1118 // We want fix that here.
michael@0 1119 if (values.getAsLong(Bookmarks.PARENT) == null && isSpecialFolder)
michael@0 1120 values.put(Bookmarks.PARENT, Bookmarks.FIXED_ROOT_ID);
michael@0 1121
michael@0 1122 if (isRootFolder && !isSpecialFolder) {
michael@0 1123 invalidSpecialEntries.add(values);
michael@0 1124 continue;
michael@0 1125 }
michael@0 1126
michael@0 1127 if (migrator != null)
michael@0 1128 migrator.updateForNewTable(values);
michael@0 1129
michael@0 1130 debug("Migrating bookmark: " + values.getAsString(Bookmarks.TITLE));
michael@0 1131 db.insert(TABLE_BOOKMARKS, Bookmarks.URL, values);
michael@0 1132
michael@0 1133 Integer type = values.getAsInteger(Bookmarks.TYPE);
michael@0 1134 if (type != null && type == Bookmarks.TYPE_FOLDER)
michael@0 1135 subFolders.add(values.getAsInteger(Bookmarks._ID));
michael@0 1136 }
michael@0 1137 } finally {
michael@0 1138 if (c != null)
michael@0 1139 c.close();
michael@0 1140 }
michael@0 1141
michael@0 1142 // At this point is safe to assume that the mobile folder is
michael@0 1143 // in the new table given that we've always created it on
michael@0 1144 // database creation time.
michael@0 1145 final int nInvalidSpecialEntries = invalidSpecialEntries.size();
michael@0 1146 if (nInvalidSpecialEntries > 0) {
michael@0 1147 Integer mobileFolderId = getMobileFolderId(db);
michael@0 1148 if (mobileFolderId == null) {
michael@0 1149 Log.e(LOGTAG, "Error migrating invalid special folder entries: mobile folder id is null");
michael@0 1150 return;
michael@0 1151 }
michael@0 1152
michael@0 1153 debug("Found " + nInvalidSpecialEntries + " invalid special folder entries");
michael@0 1154 for (int i = 0; i < nInvalidSpecialEntries; i++) {
michael@0 1155 ContentValues values = invalidSpecialEntries.get(i);
michael@0 1156 values.put(Bookmarks.PARENT, mobileFolderId);
michael@0 1157
michael@0 1158 db.insert(TABLE_BOOKMARKS, Bookmarks.URL, values);
michael@0 1159 }
michael@0 1160 }
michael@0 1161
michael@0 1162 final int nSubFolders = subFolders.size();
michael@0 1163 for (int i = 0; i < nSubFolders; i++) {
michael@0 1164 int subFolderId = subFolders.get(i);
michael@0 1165 migrateBookmarkFolder(db, subFolderId, migrator);
michael@0 1166 }
michael@0 1167 }
michael@0 1168
michael@0 1169 private void migrateBookmarksTable(SQLiteDatabase db) {
michael@0 1170 migrateBookmarksTable(db, null);
michael@0 1171 }
michael@0 1172
michael@0 1173 private void migrateBookmarksTable(SQLiteDatabase db, BookmarkMigrator migrator) {
michael@0 1174 debug("Renaming bookmarks table to " + TABLE_BOOKMARKS_TMP);
michael@0 1175 db.execSQL("ALTER TABLE " + TABLE_BOOKMARKS +
michael@0 1176 " RENAME TO " + TABLE_BOOKMARKS_TMP);
michael@0 1177
michael@0 1178 debug("Dropping views and indexes related to " + TABLE_BOOKMARKS);
michael@0 1179 db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_BOOKMARKS_WITH_IMAGES);
michael@0 1180
michael@0 1181 db.execSQL("DROP INDEX IF EXISTS bookmarks_url_index");
michael@0 1182 db.execSQL("DROP INDEX IF EXISTS bookmarks_type_deleted_index");
michael@0 1183 db.execSQL("DROP INDEX IF EXISTS bookmarks_guid_index");
michael@0 1184 db.execSQL("DROP INDEX IF EXISTS bookmarks_modified_index");
michael@0 1185
michael@0 1186 createBookmarksTable(db);
michael@0 1187 createBookmarksWithImagesView(db);
michael@0 1188
michael@0 1189 createOrUpdateSpecialFolder(db, Bookmarks.PLACES_FOLDER_GUID,
michael@0 1190 R.string.bookmarks_folder_places, 0);
michael@0 1191
michael@0 1192 migrateBookmarkFolder(db, Bookmarks.FIXED_ROOT_ID, migrator);
michael@0 1193
michael@0 1194 // Ensure all special folders exist and have the
michael@0 1195 // right folder hierarchy.
michael@0 1196 createOrUpdateAllSpecialFolders(db);
michael@0 1197
michael@0 1198 debug("Dropping bookmarks temporary table");
michael@0 1199 db.execSQL("DROP TABLE IF EXISTS " + TABLE_BOOKMARKS_TMP);
michael@0 1200 }
michael@0 1201
michael@0 1202
michael@0 1203 private void migrateHistoryTable(SQLiteDatabase db) {
michael@0 1204 debug("Renaming history table to " + TABLE_HISTORY_TMP);
michael@0 1205 db.execSQL("ALTER TABLE " + TABLE_HISTORY +
michael@0 1206 " RENAME TO " + TABLE_HISTORY_TMP);
michael@0 1207
michael@0 1208 debug("Dropping views and indexes related to " + TABLE_HISTORY);
michael@0 1209 db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_HISTORY_WITH_IMAGES);
michael@0 1210 db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
michael@0 1211
michael@0 1212 db.execSQL("DROP INDEX IF EXISTS history_url_index");
michael@0 1213 db.execSQL("DROP INDEX IF EXISTS history_guid_index");
michael@0 1214 db.execSQL("DROP INDEX IF EXISTS history_modified_index");
michael@0 1215 db.execSQL("DROP INDEX IF EXISTS history_visited_index");
michael@0 1216
michael@0 1217 createHistoryTable(db);
michael@0 1218 createHistoryWithImagesView(db);
michael@0 1219 createCombinedWithImagesView(db);
michael@0 1220
michael@0 1221 db.execSQL("INSERT INTO " + TABLE_HISTORY + " SELECT * FROM " + TABLE_HISTORY_TMP);
michael@0 1222
michael@0 1223 debug("Dropping history temporary table");
michael@0 1224 db.execSQL("DROP TABLE IF EXISTS " + TABLE_HISTORY_TMP);
michael@0 1225 }
michael@0 1226
michael@0 1227 private void migrateImagesTable(SQLiteDatabase db) {
michael@0 1228 debug("Renaming images table to " + TABLE_IMAGES_TMP);
michael@0 1229 db.execSQL("ALTER TABLE " + Obsolete.TABLE_IMAGES +
michael@0 1230 " RENAME TO " + TABLE_IMAGES_TMP);
michael@0 1231
michael@0 1232 debug("Dropping views and indexes related to " + Obsolete.TABLE_IMAGES);
michael@0 1233 db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_HISTORY_WITH_IMAGES);
michael@0 1234 db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
michael@0 1235
michael@0 1236 db.execSQL("DROP INDEX IF EXISTS images_url_index");
michael@0 1237 db.execSQL("DROP INDEX IF EXISTS images_guid_index");
michael@0 1238 db.execSQL("DROP INDEX IF EXISTS images_modified_index");
michael@0 1239
michael@0 1240 createImagesTable(db);
michael@0 1241 createHistoryWithImagesView(db);
michael@0 1242 createCombinedWithImagesView(db);
michael@0 1243
michael@0 1244 db.execSQL("INSERT INTO " + Obsolete.TABLE_IMAGES + " SELECT * FROM " + TABLE_IMAGES_TMP);
michael@0 1245
michael@0 1246 debug("Dropping images temporary table");
michael@0 1247 db.execSQL("DROP TABLE IF EXISTS " + TABLE_IMAGES_TMP);
michael@0 1248 }
michael@0 1249
michael@0 1250 private void upgradeDatabaseFrom1to2(SQLiteDatabase db) {
michael@0 1251 migrateBookmarksTable(db);
michael@0 1252 }
michael@0 1253
michael@0 1254 private void upgradeDatabaseFrom2to3(SQLiteDatabase db) {
michael@0 1255 debug("Dropping view: " + Obsolete.VIEW_BOOKMARKS_WITH_IMAGES);
michael@0 1256 db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_BOOKMARKS_WITH_IMAGES);
michael@0 1257
michael@0 1258 createBookmarksWithImagesView(db);
michael@0 1259
michael@0 1260 debug("Dropping view: " + Obsolete.VIEW_HISTORY_WITH_IMAGES);
michael@0 1261 db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_HISTORY_WITH_IMAGES);
michael@0 1262
michael@0 1263 createHistoryWithImagesView(db);
michael@0 1264 }
michael@0 1265
michael@0 1266 private void upgradeDatabaseFrom3to4(SQLiteDatabase db) {
michael@0 1267 migrateBookmarksTable(db, new BookmarkMigrator3to4());
michael@0 1268 }
michael@0 1269
michael@0 1270 private void upgradeDatabaseFrom4to5(SQLiteDatabase db) {
michael@0 1271 createCombinedWithImagesView(db);
michael@0 1272 }
michael@0 1273
michael@0 1274 private void upgradeDatabaseFrom5to6(SQLiteDatabase db) {
michael@0 1275 debug("Dropping view: " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
michael@0 1276 db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
michael@0 1277
michael@0 1278 createCombinedWithImagesView(db);
michael@0 1279 }
michael@0 1280
michael@0 1281 private void upgradeDatabaseFrom6to7(SQLiteDatabase db) {
michael@0 1282 debug("Removing history visits with NULL GUIDs");
michael@0 1283 db.execSQL("DELETE FROM " + TABLE_HISTORY + " WHERE " + History.GUID + " IS NULL");
michael@0 1284
michael@0 1285 debug("Update images with NULL GUIDs");
michael@0 1286 String[] columns = new String[] { Obsolete.Images._ID };
michael@0 1287 Cursor cursor = null;
michael@0 1288 try {
michael@0 1289 cursor = db.query(Obsolete.TABLE_IMAGES, columns, Obsolete.Images.GUID + " IS NULL", null, null ,null, null, null);
michael@0 1290 ContentValues values = new ContentValues();
michael@0 1291 if (cursor.moveToFirst()) {
michael@0 1292 do {
michael@0 1293 values.put(Obsolete.Images.GUID, Utils.generateGuid());
michael@0 1294 db.update(Obsolete.TABLE_IMAGES, values, Obsolete.Images._ID + " = ?", new String[] {
michael@0 1295 cursor.getString(cursor.getColumnIndexOrThrow(Obsolete.Images._ID))
michael@0 1296 });
michael@0 1297 } while (cursor.moveToNext());
michael@0 1298 }
michael@0 1299 } finally {
michael@0 1300 if (cursor != null)
michael@0 1301 cursor.close();
michael@0 1302 }
michael@0 1303
michael@0 1304 migrateBookmarksTable(db);
michael@0 1305 migrateHistoryTable(db);
michael@0 1306 migrateImagesTable(db);
michael@0 1307 }
michael@0 1308
michael@0 1309 private void upgradeDatabaseFrom7to8(SQLiteDatabase db) {
michael@0 1310 debug("Combining history entries with the same URL");
michael@0 1311
michael@0 1312 final String TABLE_DUPES = "duped_urls";
michael@0 1313 final String TOTAL = "total";
michael@0 1314 final String LATEST = "latest";
michael@0 1315 final String WINNER = "winner";
michael@0 1316
michael@0 1317 db.execSQL("CREATE TEMP TABLE " + TABLE_DUPES + " AS" +
michael@0 1318 " SELECT " + History.URL + ", " +
michael@0 1319 "SUM(" + History.VISITS + ") AS " + TOTAL + ", " +
michael@0 1320 "MAX(" + History.DATE_MODIFIED + ") AS " + LATEST + ", " +
michael@0 1321 "MAX(" + History._ID + ") AS " + WINNER +
michael@0 1322 " FROM " + TABLE_HISTORY +
michael@0 1323 " GROUP BY " + History.URL +
michael@0 1324 " HAVING count(" + History.URL + ") > 1");
michael@0 1325
michael@0 1326 db.execSQL("CREATE UNIQUE INDEX " + TABLE_DUPES + "_url_index ON " +
michael@0 1327 TABLE_DUPES + " (" + History.URL + ")");
michael@0 1328
michael@0 1329 final String fromClause = " FROM " + TABLE_DUPES + " WHERE " +
michael@0 1330 qualifyColumn(TABLE_DUPES, History.URL) + " = " +
michael@0 1331 qualifyColumn(TABLE_HISTORY, History.URL);
michael@0 1332
michael@0 1333 db.execSQL("UPDATE " + TABLE_HISTORY +
michael@0 1334 " SET " + History.VISITS + " = (SELECT " + TOTAL + fromClause + "), " +
michael@0 1335 History.DATE_MODIFIED + " = (SELECT " + LATEST + fromClause + "), " +
michael@0 1336 History.IS_DELETED + " = " +
michael@0 1337 "(" + History._ID + " <> (SELECT " + WINNER + fromClause + "))" +
michael@0 1338 " WHERE " + History.URL + " IN (SELECT " + History.URL + " FROM " + TABLE_DUPES + ")");
michael@0 1339
michael@0 1340 db.execSQL("DROP TABLE " + TABLE_DUPES);
michael@0 1341 }
michael@0 1342
michael@0 1343 private void upgradeDatabaseFrom8to9(SQLiteDatabase db) {
michael@0 1344 createOrUpdateSpecialFolder(db, Bookmarks.READING_LIST_FOLDER_GUID,
michael@0 1345 R.string.bookmarks_folder_reading_list, 5);
michael@0 1346
michael@0 1347 debug("Dropping view: " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
michael@0 1348 db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
michael@0 1349
michael@0 1350 createCombinedWithImagesViewOn9(db);
michael@0 1351 }
michael@0 1352
michael@0 1353 private void upgradeDatabaseFrom9to10(SQLiteDatabase db) {
michael@0 1354 debug("Dropping view: " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
michael@0 1355 db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
michael@0 1356
michael@0 1357 createCombinedWithImagesViewOn10(db);
michael@0 1358 }
michael@0 1359
michael@0 1360 private void upgradeDatabaseFrom10to11(SQLiteDatabase db) {
michael@0 1361 debug("Dropping view: " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
michael@0 1362 db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
michael@0 1363
michael@0 1364 db.execSQL("CREATE INDEX bookmarks_type_deleted_index ON " + TABLE_BOOKMARKS + "("
michael@0 1365 + Bookmarks.TYPE + ", " + Bookmarks.IS_DELETED + ")");
michael@0 1366
michael@0 1367 createCombinedWithImagesViewOn11(db);
michael@0 1368 }
michael@0 1369
michael@0 1370 private void upgradeDatabaseFrom11to12(SQLiteDatabase db) {
michael@0 1371 debug("Dropping view: " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
michael@0 1372 db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
michael@0 1373
michael@0 1374 createCombinedViewOn12(db);
michael@0 1375 }
michael@0 1376
michael@0 1377 private void upgradeDatabaseFrom12to13(SQLiteDatabase db) {
michael@0 1378 // Update images table with favicon URLs
michael@0 1379 SQLiteDatabase faviconsDb = null;
michael@0 1380 Cursor c = null;
michael@0 1381 try {
michael@0 1382 final String FAVICON_TABLE = "favicon_urls";
michael@0 1383 final String FAVICON_URL = "favicon_url";
michael@0 1384 final String FAVICON_PAGE = "page_url";
michael@0 1385
michael@0 1386 String dbPath = mContext.getDatabasePath(Obsolete.FAVICON_DB).getPath();
michael@0 1387 faviconsDb = SQLiteDatabase.openDatabase(dbPath, null, SQLiteDatabase.OPEN_READONLY);
michael@0 1388 String[] columns = new String[] { FAVICON_URL, FAVICON_PAGE };
michael@0 1389 c = faviconsDb.query(FAVICON_TABLE, columns, null, null, null, null, null, null);
michael@0 1390 int faviconIndex = c.getColumnIndexOrThrow(FAVICON_URL);
michael@0 1391 int pageIndex = c.getColumnIndexOrThrow(FAVICON_PAGE);
michael@0 1392 while (c.moveToNext()) {
michael@0 1393 ContentValues values = new ContentValues(1);
michael@0 1394 String faviconUrl = c.getString(faviconIndex);
michael@0 1395 String pageUrl = c.getString(pageIndex);
michael@0 1396 values.put(FAVICON_URL, faviconUrl);
michael@0 1397 db.update(Obsolete.TABLE_IMAGES, values, Obsolete.Images.URL + " = ?", new String[] { pageUrl });
michael@0 1398 }
michael@0 1399 } catch (SQLException e) {
michael@0 1400 // If we can't read from the database for some reason, we won't
michael@0 1401 // be able to import the favicon URLs. This isn't a fatal
michael@0 1402 // error, so continue the upgrade.
michael@0 1403 Log.e(LOGTAG, "Exception importing from " + Obsolete.FAVICON_DB, e);
michael@0 1404 } finally {
michael@0 1405 if (c != null)
michael@0 1406 c.close();
michael@0 1407 if (faviconsDb != null)
michael@0 1408 faviconsDb.close();
michael@0 1409 }
michael@0 1410
michael@0 1411 createFaviconsTable(db);
michael@0 1412
michael@0 1413 // Import favicons into the favicons table
michael@0 1414 db.execSQL("ALTER TABLE " + TABLE_HISTORY
michael@0 1415 + " ADD COLUMN " + History.FAVICON_ID + " INTEGER");
michael@0 1416 db.execSQL("ALTER TABLE " + TABLE_BOOKMARKS
michael@0 1417 + " ADD COLUMN " + Bookmarks.FAVICON_ID + " INTEGER");
michael@0 1418
michael@0 1419 try {
michael@0 1420 c = db.query(Obsolete.TABLE_IMAGES,
michael@0 1421 new String[] {
michael@0 1422 Obsolete.Images.URL,
michael@0 1423 Obsolete.Images.FAVICON_URL,
michael@0 1424 Obsolete.Images.FAVICON,
michael@0 1425 Obsolete.Images.DATE_MODIFIED,
michael@0 1426 Obsolete.Images.DATE_CREATED
michael@0 1427 },
michael@0 1428 Obsolete.Images.FAVICON + " IS NOT NULL",
michael@0 1429 null, null, null, null);
michael@0 1430
michael@0 1431 while (c.moveToNext()) {
michael@0 1432 long faviconId = -1;
michael@0 1433 int faviconUrlIndex = c.getColumnIndexOrThrow(Obsolete.Images.FAVICON_URL);
michael@0 1434 String faviconUrl = null;
michael@0 1435 if (!c.isNull(faviconUrlIndex)) {
michael@0 1436 faviconUrl = c.getString(faviconUrlIndex);
michael@0 1437 Cursor c2 = null;
michael@0 1438 try {
michael@0 1439 c2 = db.query(TABLE_FAVICONS,
michael@0 1440 new String[] { Favicons._ID },
michael@0 1441 Favicons.URL + " = ?",
michael@0 1442 new String[] { faviconUrl },
michael@0 1443 null, null, null);
michael@0 1444 if (c2.moveToFirst()) {
michael@0 1445 faviconId = c2.getLong(c2.getColumnIndexOrThrow(Favicons._ID));
michael@0 1446 }
michael@0 1447 } finally {
michael@0 1448 if (c2 != null)
michael@0 1449 c2.close();
michael@0 1450 }
michael@0 1451 }
michael@0 1452
michael@0 1453 if (faviconId == -1) {
michael@0 1454 ContentValues values = new ContentValues(4);
michael@0 1455 values.put(Favicons.URL, faviconUrl);
michael@0 1456 values.put(Favicons.DATA, c.getBlob(c.getColumnIndexOrThrow(Obsolete.Images.FAVICON)));
michael@0 1457 values.put(Favicons.DATE_MODIFIED, c.getLong(c.getColumnIndexOrThrow(Obsolete.Images.DATE_MODIFIED)));
michael@0 1458 values.put(Favicons.DATE_CREATED, c.getLong(c.getColumnIndexOrThrow(Obsolete.Images.DATE_CREATED)));
michael@0 1459 faviconId = db.insert(TABLE_FAVICONS, null, values);
michael@0 1460 }
michael@0 1461
michael@0 1462 ContentValues values = new ContentValues(1);
michael@0 1463 values.put(FaviconColumns.FAVICON_ID, faviconId);
michael@0 1464 db.update(TABLE_HISTORY, values, History.URL + " = ?",
michael@0 1465 new String[] { c.getString(c.getColumnIndexOrThrow(Obsolete.Images.URL)) });
michael@0 1466 db.update(TABLE_BOOKMARKS, values, Bookmarks.URL + " = ?",
michael@0 1467 new String[] { c.getString(c.getColumnIndexOrThrow(Obsolete.Images.URL)) });
michael@0 1468 }
michael@0 1469 } finally {
michael@0 1470 if (c != null)
michael@0 1471 c.close();
michael@0 1472 }
michael@0 1473
michael@0 1474 createThumbnailsTable(db);
michael@0 1475
michael@0 1476 // Import thumbnails into the thumbnails table
michael@0 1477 db.execSQL("INSERT INTO " + TABLE_THUMBNAILS + " ("
michael@0 1478 + Thumbnails.URL + ", "
michael@0 1479 + Thumbnails.DATA + ") "
michael@0 1480 + "SELECT " + Obsolete.Images.URL + ", " + Obsolete.Images.THUMBNAIL
michael@0 1481 + " FROM " + Obsolete.TABLE_IMAGES
michael@0 1482 + " WHERE " + Obsolete.Images.THUMBNAIL + " IS NOT NULL");
michael@0 1483
michael@0 1484 db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_BOOKMARKS_WITH_IMAGES);
michael@0 1485 db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_HISTORY_WITH_IMAGES);
michael@0 1486 db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
michael@0 1487 db.execSQL("DROP VIEW IF EXISTS " + VIEW_COMBINED);
michael@0 1488
michael@0 1489 createBookmarksWithFaviconsView(db);
michael@0 1490 createHistoryWithFaviconsView(db);
michael@0 1491 createCombinedViewOn13(db);
michael@0 1492
michael@0 1493 db.execSQL("DROP TABLE IF EXISTS " + Obsolete.TABLE_IMAGES);
michael@0 1494 }
michael@0 1495
michael@0 1496 private void upgradeDatabaseFrom13to14(SQLiteDatabase db) {
michael@0 1497 createOrUpdateSpecialFolder(db, Bookmarks.PINNED_FOLDER_GUID,
michael@0 1498 R.string.bookmarks_folder_pinned, 6);
michael@0 1499 }
michael@0 1500
michael@0 1501 private void upgradeDatabaseFrom14to15(SQLiteDatabase db) {
michael@0 1502 Cursor c = null;
michael@0 1503 try {
michael@0 1504 // Get all the pinned bookmarks
michael@0 1505 c = db.query(TABLE_BOOKMARKS,
michael@0 1506 new String[] { Bookmarks._ID, Bookmarks.URL },
michael@0 1507 Bookmarks.PARENT + " = ?",
michael@0 1508 new String[] { Integer.toString(Bookmarks.FIXED_PINNED_LIST_ID) },
michael@0 1509 null, null, null);
michael@0 1510
michael@0 1511 while (c.moveToNext()) {
michael@0 1512 // Check if this URL can be parsed as a URI with a valid scheme.
michael@0 1513 String url = c.getString(c.getColumnIndexOrThrow(Bookmarks.URL));
michael@0 1514 if (Uri.parse(url).getScheme() != null) {
michael@0 1515 continue;
michael@0 1516 }
michael@0 1517
michael@0 1518 // If it can't, update the URL to be an encoded "user-entered" value.
michael@0 1519 ContentValues values = new ContentValues(1);
michael@0 1520 String newUrl = Uri.fromParts("user-entered", url, null).toString();
michael@0 1521 values.put(Bookmarks.URL, newUrl);
michael@0 1522 db.update(TABLE_BOOKMARKS, values, Bookmarks._ID + " = ?",
michael@0 1523 new String[] { Integer.toString(c.getInt(c.getColumnIndexOrThrow(Bookmarks._ID))) });
michael@0 1524 }
michael@0 1525 } finally {
michael@0 1526 if (c != null) {
michael@0 1527 c.close();
michael@0 1528 }
michael@0 1529 }
michael@0 1530 }
michael@0 1531
michael@0 1532 private void upgradeDatabaseFrom15to16(SQLiteDatabase db) {
michael@0 1533 db.execSQL("DROP VIEW IF EXISTS " + VIEW_COMBINED);
michael@0 1534 db.execSQL("DROP VIEW IF EXISTS " + VIEW_COMBINED_WITH_FAVICONS);
michael@0 1535
michael@0 1536 createCombinedViewOn16(db);
michael@0 1537 }
michael@0 1538
michael@0 1539 private void upgradeDatabaseFrom16to17(SQLiteDatabase db) {
michael@0 1540 // Purge any 0-byte favicons/thumbnails
michael@0 1541 try {
michael@0 1542 db.execSQL("DELETE FROM " + TABLE_FAVICONS +
michael@0 1543 " WHERE length(" + Favicons.DATA + ") = 0");
michael@0 1544 db.execSQL("DELETE FROM " + TABLE_THUMBNAILS +
michael@0 1545 " WHERE length(" + Thumbnails.DATA + ") = 0");
michael@0 1546 } catch (SQLException e) {
michael@0 1547 Log.e(LOGTAG, "Error purging invalid favicons or thumbnails", e);
michael@0 1548 }
michael@0 1549 }
michael@0 1550
michael@0 1551 /*
michael@0 1552 * Moves reading list items from 'bookmarks' table to 'reading_list' table. Uses the
michael@0 1553 * same item GUID.
michael@0 1554 */
michael@0 1555 private void upgradeDatabaseFrom17to18(SQLiteDatabase db) {
michael@0 1556 debug("Moving reading list items from 'bookmarks' table to 'reading_list' table");
michael@0 1557
michael@0 1558 final String selection = Bookmarks.PARENT + " = ? AND " + Bookmarks.IS_DELETED + " = ? ";
michael@0 1559 final String[] selectionArgs = { String.valueOf(Bookmarks.FIXED_READING_LIST_ID), "0" };
michael@0 1560 final String[] projection = { Bookmarks._ID,
michael@0 1561 Bookmarks.GUID,
michael@0 1562 Bookmarks.URL,
michael@0 1563 Bookmarks.DATE_MODIFIED,
michael@0 1564 Bookmarks.DATE_CREATED,
michael@0 1565 Bookmarks.TITLE };
michael@0 1566 Cursor cursor = null;
michael@0 1567 try {
michael@0 1568 // Start transaction
michael@0 1569 db.beginTransaction();
michael@0 1570
michael@0 1571 // Create 'reading_list' table
michael@0 1572 createReadingListTable(db);
michael@0 1573
michael@0 1574 // Get all the reading list items from bookmarks table
michael@0 1575 cursor = db.query(TABLE_BOOKMARKS, projection, selection, selectionArgs,
michael@0 1576 null, null, null);
michael@0 1577
michael@0 1578 // Insert reading list items into reading_list table
michael@0 1579 while (cursor.moveToNext()) {
michael@0 1580 debug(DatabaseUtils.dumpCurrentRowToString(cursor));
michael@0 1581 ContentValues values = new ContentValues();
michael@0 1582 DatabaseUtils.cursorStringToContentValues(cursor, Bookmarks.URL, values, ReadingListItems.URL);
michael@0 1583 DatabaseUtils.cursorStringToContentValues(cursor, Bookmarks.GUID, values, ReadingListItems.GUID);
michael@0 1584 DatabaseUtils.cursorStringToContentValues(cursor, Bookmarks.TITLE, values, ReadingListItems.TITLE);
michael@0 1585 DatabaseUtils.cursorLongToContentValues(cursor, Bookmarks.DATE_CREATED, values, ReadingListItems.DATE_CREATED);
michael@0 1586 DatabaseUtils.cursorLongToContentValues(cursor, Bookmarks.DATE_MODIFIED, values, ReadingListItems.DATE_MODIFIED);
michael@0 1587
michael@0 1588 db.insertOrThrow(TABLE_READING_LIST, null, values);
michael@0 1589 }
michael@0 1590
michael@0 1591 // Delete reading list items from bookmarks table
michael@0 1592 db.delete(TABLE_BOOKMARKS,
michael@0 1593 Bookmarks.PARENT + " = ? ",
michael@0 1594 new String[] { String.valueOf(Bookmarks.FIXED_READING_LIST_ID) });
michael@0 1595
michael@0 1596 // Delete reading list special folder
michael@0 1597 db.delete(TABLE_BOOKMARKS,
michael@0 1598 Bookmarks._ID + " = ? ",
michael@0 1599 new String[] { String.valueOf(Bookmarks.FIXED_READING_LIST_ID) });
michael@0 1600 // Done
michael@0 1601 db.setTransactionSuccessful();
michael@0 1602
michael@0 1603 } catch (SQLException e) {
michael@0 1604 Log.e(LOGTAG, "Error migrating reading list items", e);
michael@0 1605 } finally {
michael@0 1606 if (cursor != null) {
michael@0 1607 cursor.close();
michael@0 1608 }
michael@0 1609 db.endTransaction();
michael@0 1610 }
michael@0 1611 }
michael@0 1612
michael@0 1613 @Override
michael@0 1614 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
michael@0 1615 debug("Upgrading browser.db: " + db.getPath() + " from " +
michael@0 1616 oldVersion + " to " + newVersion);
michael@0 1617
michael@0 1618 // We have to do incremental upgrades until we reach the current
michael@0 1619 // database schema version.
michael@0 1620 for (int v = oldVersion + 1; v <= newVersion; v++) {
michael@0 1621 switch(v) {
michael@0 1622 case 2:
michael@0 1623 upgradeDatabaseFrom1to2(db);
michael@0 1624 break;
michael@0 1625
michael@0 1626 case 3:
michael@0 1627 upgradeDatabaseFrom2to3(db);
michael@0 1628 break;
michael@0 1629
michael@0 1630 case 4:
michael@0 1631 upgradeDatabaseFrom3to4(db);
michael@0 1632 break;
michael@0 1633
michael@0 1634 case 5:
michael@0 1635 upgradeDatabaseFrom4to5(db);
michael@0 1636 break;
michael@0 1637
michael@0 1638 case 6:
michael@0 1639 upgradeDatabaseFrom5to6(db);
michael@0 1640 break;
michael@0 1641
michael@0 1642 case 7:
michael@0 1643 upgradeDatabaseFrom6to7(db);
michael@0 1644 break;
michael@0 1645
michael@0 1646 case 8:
michael@0 1647 upgradeDatabaseFrom7to8(db);
michael@0 1648 break;
michael@0 1649
michael@0 1650 case 9:
michael@0 1651 upgradeDatabaseFrom8to9(db);
michael@0 1652 break;
michael@0 1653
michael@0 1654 case 10:
michael@0 1655 upgradeDatabaseFrom9to10(db);
michael@0 1656 break;
michael@0 1657
michael@0 1658 case 11:
michael@0 1659 upgradeDatabaseFrom10to11(db);
michael@0 1660 break;
michael@0 1661
michael@0 1662 case 12:
michael@0 1663 upgradeDatabaseFrom11to12(db);
michael@0 1664 break;
michael@0 1665
michael@0 1666 case 13:
michael@0 1667 upgradeDatabaseFrom12to13(db);
michael@0 1668 break;
michael@0 1669
michael@0 1670 case 14:
michael@0 1671 upgradeDatabaseFrom13to14(db);
michael@0 1672 break;
michael@0 1673
michael@0 1674 case 15:
michael@0 1675 upgradeDatabaseFrom14to15(db);
michael@0 1676 break;
michael@0 1677
michael@0 1678 case 16:
michael@0 1679 upgradeDatabaseFrom15to16(db);
michael@0 1680 break;
michael@0 1681
michael@0 1682 case 17:
michael@0 1683 upgradeDatabaseFrom16to17(db);
michael@0 1684 break;
michael@0 1685
michael@0 1686 case 18:
michael@0 1687 upgradeDatabaseFrom17to18(db);
michael@0 1688 break;
michael@0 1689 }
michael@0 1690 }
michael@0 1691
michael@0 1692 // If an upgrade after 12->13 fails, the entire upgrade is rolled
michael@0 1693 // back, but we can't undo the deletion of favicon_urls.db if we
michael@0 1694 // delete this in step 13; therefore, we wait until all steps are
michael@0 1695 // complete before removing it.
michael@0 1696 if (oldVersion < 13 && newVersion >= 13
michael@0 1697 && mContext.getDatabasePath(Obsolete.FAVICON_DB).exists()
michael@0 1698 && !mContext.deleteDatabase(Obsolete.FAVICON_DB)) {
michael@0 1699 throw new SQLException("Could not delete " + Obsolete.FAVICON_DB);
michael@0 1700 }
michael@0 1701 }
michael@0 1702
michael@0 1703 @Override
michael@0 1704 public void onOpen(SQLiteDatabase db) {
michael@0 1705 debug("Opening browser.db: " + db.getPath());
michael@0 1706
michael@0 1707 Cursor cursor = null;
michael@0 1708 try {
michael@0 1709 cursor = db.rawQuery("PRAGMA foreign_keys=ON", null);
michael@0 1710 } finally {
michael@0 1711 if (cursor != null)
michael@0 1712 cursor.close();
michael@0 1713 }
michael@0 1714 cursor = null;
michael@0 1715 try {
michael@0 1716 cursor = db.rawQuery("PRAGMA synchronous=NORMAL", null);
michael@0 1717 } finally {
michael@0 1718 if (cursor != null)
michael@0 1719 cursor.close();
michael@0 1720 }
michael@0 1721
michael@0 1722 // From Honeycomb on, it's possible to run several db
michael@0 1723 // commands in parallel using multiple connections.
michael@0 1724 if (Build.VERSION.SDK_INT >= 11) {
michael@0 1725 db.enableWriteAheadLogging();
michael@0 1726 db.setLockingEnabled(false);
michael@0 1727 } else {
michael@0 1728 // Pre-Honeycomb, we can do some lesser optimizations.
michael@0 1729 cursor = null;
michael@0 1730 try {
michael@0 1731 cursor = db.rawQuery("PRAGMA journal_mode=PERSIST", null);
michael@0 1732 } finally {
michael@0 1733 if (cursor != null)
michael@0 1734 cursor.close();
michael@0 1735 }
michael@0 1736 }
michael@0 1737 }
michael@0 1738
michael@0 1739 static final String qualifyColumn(String table, String column) {
michael@0 1740 return DBUtils.qualifyColumn(table, column);
michael@0 1741 }
michael@0 1742
michael@0 1743 // Calculate these once, at initialization. isLoggable is too expensive to
michael@0 1744 // have in-line in each log call.
michael@0 1745 private static boolean logDebug = Log.isLoggable(LOGTAG, Log.DEBUG);
michael@0 1746 private static boolean logVerbose = Log.isLoggable(LOGTAG, Log.VERBOSE);
michael@0 1747 protected static void trace(String message) {
michael@0 1748 if (logVerbose) {
michael@0 1749 Log.v(LOGTAG, message);
michael@0 1750 }
michael@0 1751 }
michael@0 1752
michael@0 1753 protected static void debug(String message) {
michael@0 1754 if (logDebug) {
michael@0 1755 Log.d(LOGTAG, message);
michael@0 1756 }
michael@0 1757 }
michael@0 1758
michael@0 1759 private Integer getMobileFolderId(SQLiteDatabase db) {
michael@0 1760 Cursor c = null;
michael@0 1761
michael@0 1762 try {
michael@0 1763 c = db.query(TABLE_BOOKMARKS,
michael@0 1764 mobileIdColumns,
michael@0 1765 Bookmarks.GUID + " = ?",
michael@0 1766 mobileIdSelectionArgs,
michael@0 1767 null, null, null);
michael@0 1768
michael@0 1769 if (c == null || !c.moveToFirst())
michael@0 1770 return null;
michael@0 1771
michael@0 1772 return c.getInt(c.getColumnIndex(Bookmarks._ID));
michael@0 1773 } finally {
michael@0 1774 if (c != null)
michael@0 1775 c.close();
michael@0 1776 }
michael@0 1777 }
michael@0 1778
michael@0 1779 private long insertFavicon(SQLiteDatabase db, ContentValues values) {
michael@0 1780 // This method is a dupicate of BrowserProvider.insertFavicon.
michael@0 1781 // If changes are needed, please update both
michael@0 1782 String faviconUrl = values.getAsString(Favicons.URL);
michael@0 1783 String pageUrl = null;
michael@0 1784 long faviconId;
michael@0 1785
michael@0 1786 trace("Inserting favicon for URL: " + faviconUrl);
michael@0 1787
michael@0 1788 DBUtils.stripEmptyByteArray(values, Favicons.DATA);
michael@0 1789
michael@0 1790 // Extract the page URL from the ContentValues
michael@0 1791 if (values.containsKey(Favicons.PAGE_URL)) {
michael@0 1792 pageUrl = values.getAsString(Favicons.PAGE_URL);
michael@0 1793 values.remove(Favicons.PAGE_URL);
michael@0 1794 }
michael@0 1795
michael@0 1796 // If no URL is provided, insert using the default one.
michael@0 1797 if (TextUtils.isEmpty(faviconUrl) && !TextUtils.isEmpty(pageUrl)) {
michael@0 1798 values.put(Favicons.URL, org.mozilla.gecko.favicons.Favicons.guessDefaultFaviconURL(pageUrl));
michael@0 1799 }
michael@0 1800
michael@0 1801 long now = System.currentTimeMillis();
michael@0 1802 values.put(Favicons.DATE_CREATED, now);
michael@0 1803 values.put(Favicons.DATE_MODIFIED, now);
michael@0 1804 faviconId = db.insertOrThrow(TABLE_FAVICONS, null, values);
michael@0 1805
michael@0 1806 if (pageUrl != null) {
michael@0 1807 ContentValues updateValues = new ContentValues(1);
michael@0 1808 updateValues.put(FaviconColumns.FAVICON_ID, faviconId);
michael@0 1809 db.update(TABLE_HISTORY,
michael@0 1810 updateValues,
michael@0 1811 History.URL + " = ?",
michael@0 1812 new String[] { pageUrl });
michael@0 1813 db.update(TABLE_BOOKMARKS,
michael@0 1814 updateValues,
michael@0 1815 Bookmarks.URL + " = ?",
michael@0 1816 new String[] { pageUrl });
michael@0 1817 }
michael@0 1818
michael@0 1819 return faviconId;
michael@0 1820 }
michael@0 1821
michael@0 1822 private interface BookmarkMigrator {
michael@0 1823 public void updateForNewTable(ContentValues bookmark);
michael@0 1824 }
michael@0 1825
michael@0 1826 private class BookmarkMigrator3to4 implements BookmarkMigrator {
michael@0 1827 @Override
michael@0 1828 public void updateForNewTable(ContentValues bookmark) {
michael@0 1829 Integer isFolder = bookmark.getAsInteger("folder");
michael@0 1830 if (isFolder == null || isFolder != 1) {
michael@0 1831 bookmark.put(Bookmarks.TYPE, Bookmarks.TYPE_BOOKMARK);
michael@0 1832 } else {
michael@0 1833 bookmark.put(Bookmarks.TYPE, Bookmarks.TYPE_FOLDER);
michael@0 1834 }
michael@0 1835
michael@0 1836 bookmark.remove("folder");
michael@0 1837 }
michael@0 1838 }
michael@0 1839 }

mercurial