Skip to content

Commit

Permalink
Android version
Browse files Browse the repository at this point in the history
  • Loading branch information
helmac committed Apr 10, 2019
1 parent 894298f commit 44ca051
Showing 1 changed file with 56 additions and 50 deletions.
106 changes: 56 additions & 50 deletions src/android/MigrateStorage.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.migrate.android;

import android.app.Activity;
import android.os.Build;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
Expand All @@ -18,9 +20,9 @@
/**
* Main class that is instantiated by cordova
* Acts as a "bridge" between the SDK and the cordova layer
*
*
* This plugin migrates WebSQL and localStorage from the old webview to the new webview
*
*
* TODO
* - Test if we can we remove old file:// keys?
* - Properly handle exceptions? We have a catch-all at the moment that is dealt with in the `initialize` function
Expand All @@ -33,11 +35,40 @@ public class MigrateStorage extends CordovaPlugin {
private static final String TAG = "com.migrate.android";
private static final String FILE_PROTOCOL = "file://";
private static final String WEBSQL_FILE_DIR_NAME = "file__0";
private static final String DEFAULT_PORT_NUMBER = "8080";
private static final String DEFAULT_PORT_NUMBER = "0";
private static final String CDV_SETTING_PORT_NUMBER = "WKPort";

// Root dir for system webview data used by Android 4.4+
private static String modernWebviewDir = "/app_webview";

// Root dir for system webview data used by Android 4.3 and below
private static String oldWebviewDir = "/app_database";

// Directory name for local storage files used by Android 4.4+ and XWalk
private static String modernLocalStorageDir = "/Local Storage";

// Directory name for local storage files used by Android 4.3 and below
private static String oldLocalStorageDir = "/localstorage";

private String portNumber;
private boolean isModernAndroid;
private Activity activity;

private String getWebviewPath(){
if(isModernAndroid){
return modernWebviewDir;
}else{
return oldWebviewDir;
}
}

private String getWebviewLocalStoragePath(){
if(isModernAndroid){
return modernLocalStorageDir;
}else{
return oldLocalStorageDir;
}
}

private void logDebug(String message) {
if(DEBUG_MODE) Log.d(TAG, message);
Expand All @@ -57,11 +88,11 @@ private String getRootPath() {
}

private String getWebViewRootPath() {
return this.getRootPath() + "/app_webview";
return this.getRootPath() + this.getWebviewPath();
}

private String getLocalStorageRootPath() {
return this.getWebViewRootPath() + "/Local Storage";
return this.getWebViewRootPath() + this.getWebviewLocalStoragePath();
}

private String getWebSQLDatabasesPath() {
Expand All @@ -82,55 +113,28 @@ private String getWebSQLReferenceDbPath() {
private void migrateLocalStorage() throws Exception {
this.logDebug("migrateLocalStorage: Migrating localStorage..");

String levelDbPath = this.getLocalStorageRootPath() + "/leveldb";
this.logDebug("migrateLocalStorage: levelDbPath: " + levelDbPath);

File levelDbDir = new File(levelDbPath);
if(!levelDbDir.isDirectory() || !levelDbDir.exists()) {
this.logDebug("migrateLocalStorage: '" + levelDbPath + "' is not a directory or was not found; Exiting");
return;
}
boolean hasMigratedData = false;

LevelDB db = new LevelDB(levelDbPath);
File fileLocalStorage = new File(this.getLocalStorageRootPath() + "/" + WEBSQL_FILE_DIR_NAME + ".localstorage");
File fileLocalStorageJournal = new File(this.getLocalStorageRootPath() + "/" + WEBSQL_FILE_DIR_NAME + ".localstorage-journal");

String localHostProtocol = this.getLocalHostProtocol();
File ionicLocalStorage = new File(this.getLocalStorageRootPath() + "/" + this.getLocalHostProtocolDirName() + ".localstorage");
File ionicLocalStorageJournal = new File(this.getLocalStorageRootPath() + "/" + this.getLocalHostProtocolDirName() + ".localstorage-journal");

if(db.exists(Utils.stringToBytes("META:" + localHostProtocol))) {
this.logDebug("migrateLocalStorage: Found 'META:" + localHostProtocol + "' key; Skipping migration");
db.close();
return;
if (fileLocalStorage.exists()) {
fileLocalStorage.renameTo(ionicLocalStorage);
hasMigratedData = true;
}

// Yes, there is a typo here; `newInterator` 😔
LevelIterator iterator = db.newInterator();

// To update in bulk!
WriteBatch batch = new WriteBatch();


// 🔃 Loop through the keys and replace `file://` with `http://localhost:{portNumber}`
logDebug("migrateLocalStorage: Starting replacements;");
for(iterator.seekToFirst(); iterator.isValid(); iterator.next()) {
String key = Utils.bytesToString(iterator.key());
byte[] value = iterator.value();

if (key.contains(FILE_PROTOCOL)) {
String newKey = key.replace(FILE_PROTOCOL, localHostProtocol);

logDebug("migrateLocalStorage: Changing key:" + key + " to '" + newKey + "'");

// Add new key to db
batch.putBytes(Utils.stringToBytes(newKey), value);
} else {
logDebug("migrateLocalStorage: Skipping key:" + key);
}
if (fileLocalStorageJournal.exists()) {
fileLocalStorageJournal.renameTo(ionicLocalStorageJournal);
hasMigratedData = true;
}

// Commit batch to DB
db.write(batch);

iterator.close();
db.close();
if(hasMigratedData){
Log.d(TAG, "restarting Cordova activity");
activity.recreate();
}

this.logDebug("migrateLocalStorage: Successfully migrated localStorage..");
}
Expand Down Expand Up @@ -171,15 +175,15 @@ private void migrateWebSQL() {

// Update reference DB to point to `localhost:{portNumber}`
db.execSQL("UPDATE Databases SET origin = ? WHERE origin = ?", new String[] { localHostDirName, WEBSQL_FILE_DIR_NAME });

// rename `databases/file__0` dir to `databases/localhost_http_{portNumber}`
boolean renamed = originalWebSQLDir.renameTo(targetWebSQLDir);

if(!renamed) {
logDebug("migrateWebSQL: Tried renaming '" + originalWebSQLDir.getAbsolutePath() + "' to '" + targetWebSQLDir.getAbsolutePath() + "' but failed; Exiting...");
return;
}

db.close();

this.logDebug("migrateWebSQL: Successfully migrated WebSQL..");
Expand All @@ -196,13 +200,15 @@ public void initialize(CordovaInterface cordova, CordovaWebView webView) {
try {
super.initialize(cordova, webView);

activity = cordova.getActivity();
this.isModernAndroid = Build.VERSION.SDK_INT >= 19;
this.portNumber = this.preferences.getString(CDV_SETTING_PORT_NUMBER, "");
if(this.portNumber.isEmpty() || this.portNumber == null) this.portNumber = DEFAULT_PORT_NUMBER;

logDebug("Starting migration;");

this.migrateLocalStorage();
this.migrateWebSQL();
// this.migrateWebSQL();

logDebug("Migration completed;");
} catch (Exception ex) {
Expand Down

0 comments on commit 44ca051

Please sign in to comment.