2018-01-24 19:17:44 -08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2018 Open Whisper Systems
|
2012-09-30 19:56:29 -07:00
|
|
|
*
|
2011-12-20 10:20:44 -08:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2012-09-30 19:56:29 -07:00
|
|
|
*
|
2011-12-20 10:20:44 -08:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
package org.thoughtcrime.securesms.database;
|
|
|
|
|
|
|
|
import android.content.Context;
|
2018-01-24 19:17:44 -08:00
|
|
|
import android.support.annotation.NonNull;
|
2012-09-30 19:56:29 -07:00
|
|
|
|
2018-01-24 19:17:44 -08:00
|
|
|
import net.sqlcipher.database.SQLiteDatabase;
|
2017-07-26 09:59:15 -07:00
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 12:22:04 -07:00
|
|
|
import org.thoughtcrime.securesms.DatabaseUpgradeActivity;
|
2015-07-14 14:31:03 -07:00
|
|
|
import org.thoughtcrime.securesms.contacts.ContactsDatabase;
|
2018-01-24 19:17:44 -08:00
|
|
|
import org.thoughtcrime.securesms.crypto.AttachmentSecret;
|
|
|
|
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider;
|
|
|
|
import org.thoughtcrime.securesms.crypto.DatabaseSecret;
|
|
|
|
import org.thoughtcrime.securesms.crypto.DatabaseSecretProvider;
|
2014-11-03 15:16:04 -08:00
|
|
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
2018-01-24 19:17:44 -08:00
|
|
|
import org.thoughtcrime.securesms.database.helpers.ClassicOpenHelper;
|
|
|
|
import org.thoughtcrime.securesms.database.helpers.SQLCipherMigrationHelper;
|
|
|
|
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
2017-07-26 09:59:15 -07:00
|
|
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
2013-04-26 11:23:43 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
public class DatabaseFactory {
|
2012-09-30 19:56:29 -07:00
|
|
|
|
2018-01-24 19:17:44 -08:00
|
|
|
private static final Object lock = new Object();
|
2012-09-30 19:56:29 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
private static DatabaseFactory instance;
|
2012-09-30 19:56:29 -07:00
|
|
|
|
2018-01-24 19:17:44 -08:00
|
|
|
private final SQLCipherOpenHelper databaseHelper;
|
|
|
|
private final SmsDatabase sms;
|
|
|
|
private final MmsDatabase mms;
|
|
|
|
private final AttachmentDatabase attachments;
|
|
|
|
private final MediaDatabase media;
|
|
|
|
private final ThreadDatabase thread;
|
|
|
|
private final MmsSmsDatabase mmsSmsDatabase;
|
|
|
|
private final IdentityDatabase identityDatabase;
|
|
|
|
private final DraftDatabase draftDatabase;
|
|
|
|
private final PushDatabase pushDatabase;
|
|
|
|
private final GroupDatabase groupDatabase;
|
|
|
|
private final RecipientDatabase recipientDatabase;
|
|
|
|
private final ContactsDatabase contactsDatabase;
|
2017-09-30 08:45:45 -07:00
|
|
|
private final GroupReceiptDatabase groupReceiptDatabase;
|
2012-09-30 19:56:29 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
public static DatabaseFactory getInstance(Context context) {
|
|
|
|
synchronized (lock) {
|
|
|
|
if (instance == null)
|
2015-05-21 02:32:38 -07:00
|
|
|
instance = new DatabaseFactory(context.getApplicationContext());
|
2012-09-30 19:56:29 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
return instance;
|
|
|
|
}
|
|
|
|
}
|
2012-09-30 19:56:29 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
public static MmsSmsDatabase getMmsSmsDatabase(Context context) {
|
|
|
|
return getInstance(context).mmsSmsDatabase;
|
|
|
|
}
|
2012-09-30 19:56:29 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
public static ThreadDatabase getThreadDatabase(Context context) {
|
|
|
|
return getInstance(context).thread;
|
|
|
|
}
|
2012-09-30 19:56:29 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
public static SmsDatabase getSmsDatabase(Context context) {
|
|
|
|
return getInstance(context).sms;
|
|
|
|
}
|
2012-09-30 19:56:29 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
public static MmsDatabase getMmsDatabase(Context context) {
|
|
|
|
return getInstance(context).mms;
|
|
|
|
}
|
2012-09-30 19:56:29 -07:00
|
|
|
|
2015-10-12 18:25:05 -07:00
|
|
|
public static AttachmentDatabase getAttachmentDatabase(Context context) {
|
|
|
|
return getInstance(context).attachments;
|
|
|
|
}
|
|
|
|
|
2017-02-01 03:49:19 +01:00
|
|
|
public static MediaDatabase getMediaDatabase(Context context) {
|
|
|
|
return getInstance(context).media;
|
2011-12-20 10:20:44 -08:00
|
|
|
}
|
2012-09-30 19:56:29 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
public static IdentityDatabase getIdentityDatabase(Context context) {
|
|
|
|
return getInstance(context).identityDatabase;
|
|
|
|
}
|
|
|
|
|
2013-02-04 00:13:07 -08:00
|
|
|
public static DraftDatabase getDraftDatabase(Context context) {
|
|
|
|
return getInstance(context).draftDatabase;
|
|
|
|
}
|
|
|
|
|
2013-09-08 18:19:05 -07:00
|
|
|
public static PushDatabase getPushDatabase(Context context) {
|
|
|
|
return getInstance(context).pushDatabase;
|
|
|
|
}
|
|
|
|
|
2014-01-14 00:26:43 -08:00
|
|
|
public static GroupDatabase getGroupDatabase(Context context) {
|
|
|
|
return getInstance(context).groupDatabase;
|
|
|
|
}
|
|
|
|
|
2017-08-21 18:47:37 -07:00
|
|
|
public static RecipientDatabase getRecipientDatabase(Context context) {
|
2017-08-21 18:37:39 -07:00
|
|
|
return getInstance(context).recipientDatabase;
|
2015-06-09 07:37:20 -07:00
|
|
|
}
|
|
|
|
|
2015-07-14 14:31:03 -07:00
|
|
|
public static ContactsDatabase getContactsDatabase(Context context) {
|
|
|
|
return getInstance(context).contactsDatabase;
|
|
|
|
}
|
|
|
|
|
2017-09-30 08:45:45 -07:00
|
|
|
public static GroupReceiptDatabase getGroupReceiptDatabase(Context context) {
|
|
|
|
return getInstance(context).groupReceiptDatabase;
|
|
|
|
}
|
|
|
|
|
2018-01-24 19:17:44 -08:00
|
|
|
private DatabaseFactory(@NonNull Context context) {
|
|
|
|
SQLiteDatabase.loadLibs(context);
|
|
|
|
|
|
|
|
DatabaseSecret databaseSecret = new DatabaseSecretProvider(context).getOrCreateDatabaseSecret();
|
|
|
|
AttachmentSecret attachmentSecret = AttachmentSecretProvider.getInstance(context).getOrCreateAttachmentSecret();
|
|
|
|
|
|
|
|
this.databaseHelper = new SQLCipherOpenHelper(context, databaseSecret);
|
2017-09-30 08:45:45 -07:00
|
|
|
this.sms = new SmsDatabase(context, databaseHelper);
|
|
|
|
this.mms = new MmsDatabase(context, databaseHelper);
|
2018-01-24 19:17:44 -08:00
|
|
|
this.attachments = new AttachmentDatabase(context, databaseHelper, attachmentSecret);
|
2017-09-30 08:45:45 -07:00
|
|
|
this.media = new MediaDatabase(context, databaseHelper);
|
|
|
|
this.thread = new ThreadDatabase(context, databaseHelper);
|
|
|
|
this.mmsSmsDatabase = new MmsSmsDatabase(context, databaseHelper);
|
|
|
|
this.identityDatabase = new IdentityDatabase(context, databaseHelper);
|
|
|
|
this.draftDatabase = new DraftDatabase(context, databaseHelper);
|
|
|
|
this.pushDatabase = new PushDatabase(context, databaseHelper);
|
|
|
|
this.groupDatabase = new GroupDatabase(context, databaseHelper);
|
|
|
|
this.recipientDatabase = new RecipientDatabase(context, databaseHelper);
|
|
|
|
this.groupReceiptDatabase = new GroupReceiptDatabase(context, databaseHelper);
|
|
|
|
this.contactsDatabase = new ContactsDatabase(context);
|
2011-12-20 10:20:44 -08:00
|
|
|
}
|
2012-09-30 19:56:29 -07:00
|
|
|
|
2018-01-24 19:17:44 -08:00
|
|
|
public void onApplicationLevelUpgrade(@NonNull Context context, @NonNull MasterSecret masterSecret,
|
|
|
|
int fromVersion, DatabaseUpgradeActivity.DatabaseUpgradeListener listener)
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 12:22:04 -07:00
|
|
|
{
|
2018-01-31 17:49:08 -08:00
|
|
|
databaseHelper.getWritableDatabase();
|
|
|
|
|
2018-01-24 19:17:44 -08:00
|
|
|
ClassicOpenHelper legacyOpenHelper = null;
|
2014-07-18 20:29:00 -07:00
|
|
|
|
|
|
|
if (fromVersion < DatabaseUpgradeActivity.ASYMMETRIC_MASTER_SECRET_FIX_VERSION) {
|
2018-01-24 19:17:44 -08:00
|
|
|
legacyOpenHelper = new ClassicOpenHelper(context);
|
|
|
|
legacyOpenHelper.onApplicationLevelUpgrade(context, masterSecret, fromVersion, listener);
|
2011-12-20 10:20:44 -08:00
|
|
|
}
|
|
|
|
|
2018-01-24 19:17:44 -08:00
|
|
|
if (fromVersion < DatabaseUpgradeActivity.SQLCIPHER && TextSecurePreferences.getNeedsSqlCipherMigration(context)) {
|
|
|
|
if (legacyOpenHelper == null) {
|
|
|
|
legacyOpenHelper = new ClassicOpenHelper(context);
|
2013-01-06 13:13:14 -08:00
|
|
|
}
|
2013-02-04 00:13:07 -08:00
|
|
|
|
2018-01-24 19:17:44 -08:00
|
|
|
SQLCipherMigrationHelper.migrateCiphertext(context, masterSecret,
|
|
|
|
legacyOpenHelper.getWritableDatabase(),
|
|
|
|
databaseHelper.getWritableDatabase());
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 12:22:04 -07:00
|
|
|
}
|
2011-12-20 10:20:44 -08:00
|
|
|
}
|
2017-07-26 09:59:15 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
}
|