179 lines
6.0 KiB
Java
179 lines
6.0 KiB
Java
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||
|
//
|
||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
// you may not use this file except in compliance with the License.
|
||
|
// You may obtain a copy of the License at
|
||
|
//
|
||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||
|
//
|
||
|
// Unless required by applicable law or agreed to in writing, software
|
||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
// See the License for the specific language governing permissions and
|
||
|
// limitations under the License.
|
||
|
|
||
|
package com.moodle.moodlemobile;
|
||
|
|
||
|
import android.os.Build;
|
||
|
import android.util.Log;
|
||
|
import android.content.Context;
|
||
|
import android.content.SharedPreferences;
|
||
|
import java.security.GeneralSecurityException;
|
||
|
import java.io.IOException;
|
||
|
|
||
|
import org.json.JSONArray;
|
||
|
import org.json.JSONObject;
|
||
|
import org.json.JSONException;
|
||
|
import org.apache.cordova.CordovaPlugin;
|
||
|
import org.apache.cordova.CallbackContext;
|
||
|
import org.apache.cordova.PluginResult;
|
||
|
|
||
|
import com.adobe.phonegap.push.EncryptionHandler;
|
||
|
|
||
|
public class SecureStorage extends CordovaPlugin {
|
||
|
|
||
|
private static final String TAG = "SecureStorage";
|
||
|
private static final String SHARED_PREFS_NAME = "moodlemobile_shared_prefs";
|
||
|
|
||
|
@Override
|
||
|
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) {
|
||
|
try {
|
||
|
switch (action) {
|
||
|
case "get":
|
||
|
callbackContext.success(this.get(args.getJSONArray(0), args.getString(1)));
|
||
|
|
||
|
return true;
|
||
|
case "store":
|
||
|
this.store(args.getJSONObject(0), args.getString(1));
|
||
|
callbackContext.success();
|
||
|
|
||
|
return true;
|
||
|
case "delete":
|
||
|
this.delete(args.getJSONArray(0), args.getString(1));
|
||
|
callbackContext.success();
|
||
|
|
||
|
return true;
|
||
|
case "deleteCollection":
|
||
|
this.deleteCollection(args.getString(0));
|
||
|
callbackContext.success();
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
} catch (Throwable e) {
|
||
|
Log.e(TAG, "Failed executing action: " + action, e);
|
||
|
callbackContext.error(e.getMessage());
|
||
|
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR));
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get several values from secure storage.
|
||
|
*
|
||
|
* @param names List of names to get.
|
||
|
* @param collection The collection where the values are stored.
|
||
|
* @return Values for each name.
|
||
|
*/
|
||
|
private JSONObject get(JSONArray names, String collection) throws GeneralSecurityException, IOException, JSONException {
|
||
|
Context context = this.cordova.getActivity().getApplicationContext();
|
||
|
SharedPreferences sharedPreferences = getSharedPreferences(collection);
|
||
|
JSONObject result = new JSONObject();
|
||
|
|
||
|
Log.d(TAG, "Get values with names " + names.toString());
|
||
|
|
||
|
for(int i = 0; i < names.length(); i++) {
|
||
|
String name = names.optString(i);
|
||
|
|
||
|
if (name == null || name.isEmpty()) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
String rawValue = sharedPreferences.getString(name, null);
|
||
|
if (rawValue == null) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
result.put(name, EncryptionHandler.Companion.decrypt(context, rawValue));
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Store data in secure storage.
|
||
|
*
|
||
|
* @param data Data to store, using a name -> value format.
|
||
|
* @param collection The collection where to store the values.
|
||
|
*/
|
||
|
private void store(JSONObject data, String collection) throws GeneralSecurityException, IOException, JSONException {
|
||
|
Context context = this.cordova.getActivity().getApplicationContext();
|
||
|
SharedPreferences sharedPreferences = getSharedPreferences(collection);
|
||
|
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||
|
JSONArray names = data.names();
|
||
|
|
||
|
Log.d(TAG, "Store values with names " + names.toString());
|
||
|
|
||
|
for(int i = 0; i < names.length(); i++) {
|
||
|
String name = names.optString(i);
|
||
|
|
||
|
if (name != null && !name.isEmpty()) {
|
||
|
editor.putString(name, EncryptionHandler.Companion.encrypt(context, data.getString(name)));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
editor.apply();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Delete some values from secure storage.
|
||
|
*
|
||
|
* @param names Names to delete.
|
||
|
* @param collection The collection where to delete the values.
|
||
|
*/
|
||
|
private void delete(JSONArray names, String collection) throws GeneralSecurityException, IOException {
|
||
|
Log.d(TAG, "Delete value with names " + names.toString());
|
||
|
|
||
|
SharedPreferences sharedPreferences = getSharedPreferences(collection);
|
||
|
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||
|
|
||
|
for(int i = 0; i < names.length(); i++) {
|
||
|
String name = names.optString(i);
|
||
|
|
||
|
if (name != null && !name.isEmpty()) {
|
||
|
editor.remove(name);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
editor.apply();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Delete all values from a collection.
|
||
|
*
|
||
|
* @param collection The collection to delete.
|
||
|
*/
|
||
|
private void deleteCollection(String collection) throws GeneralSecurityException, IOException {
|
||
|
Log.d(TAG, "Delete all values in collection " + collection);
|
||
|
|
||
|
SharedPreferences sharedPreferences = getSharedPreferences(collection);
|
||
|
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||
|
editor.clear();
|
||
|
editor.apply();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get shared preferences instance.
|
||
|
*
|
||
|
* @param collection The collection to use.
|
||
|
* @return Shared preferences instance.
|
||
|
*/
|
||
|
private SharedPreferences getSharedPreferences(String collection) {
|
||
|
return this.cordova.getActivity().getApplicationContext().getSharedPreferences(
|
||
|
SHARED_PREFS_NAME + "_" + collection,
|
||
|
Context.MODE_PRIVATE
|
||
|
);
|
||
|
}
|
||
|
|
||
|
}
|