зеркало из https://github.com/mozilla/gecko-dev.git
Bug 726382 - Fold the GeckoDirProvider and a bunch of duplicated/complicated code into a new GeckoProfile class. r=wesj
This commit is contained in:
Родитель
29ebf3fd2b
Коммит
22371719c3
|
@ -367,25 +367,6 @@ public class AboutHomeContent extends ScrollView {
|
|||
super.onConfigurationChanged(newConfig);
|
||||
}
|
||||
|
||||
private String readJSONFile(Activity activity, String filename) {
|
||||
InputStream fileStream = null;
|
||||
File profileDir = GeckoApp.mAppContext.getProfileDir();
|
||||
|
||||
if (profileDir == null)
|
||||
return null;
|
||||
|
||||
File recommendedAddonsFile = new File(profileDir, filename);
|
||||
if (recommendedAddonsFile.exists()) {
|
||||
try {
|
||||
fileStream = new FileInputStream(recommendedAddonsFile);
|
||||
} catch (FileNotFoundException fnfe) {}
|
||||
}
|
||||
if (fileStream == null)
|
||||
return null;
|
||||
|
||||
return readStringFromStream(fileStream);
|
||||
}
|
||||
|
||||
private String readFromZipFile(Activity activity, String filename) {
|
||||
ZipFile zip = null;
|
||||
String str = null;
|
||||
|
@ -459,9 +440,11 @@ public class AboutHomeContent extends ScrollView {
|
|||
|
||||
private void readRecommendedAddons(final Activity activity) {
|
||||
final String addonsFilename = "recommended-addons.json";
|
||||
String jsonString = readJSONFile(activity, addonsFilename);
|
||||
if (jsonString == null) {
|
||||
Log.i("Addons", "filestream is null");
|
||||
String jsonString;
|
||||
try {
|
||||
jsonString = GeckoApp.mAppContext.getProfile().readFile(addonsFilename);
|
||||
} catch (IOException ioe) {
|
||||
Log.i(LOGTAG, "filestream is null");
|
||||
jsonString = readFromZipFile(activity, addonsFilename);
|
||||
}
|
||||
|
||||
|
@ -524,33 +507,13 @@ public class AboutHomeContent extends ScrollView {
|
|||
}
|
||||
|
||||
private void readLastTabs(final Activity activity) {
|
||||
final String sessionFilename;
|
||||
if (!GeckoApp.sIsGeckoReady) {
|
||||
File profileDir = GeckoApp.mAppContext.getProfileDir();
|
||||
if (profileDir == null)
|
||||
return;
|
||||
|
||||
if (new File(profileDir, "sessionstore.js").exists()) {
|
||||
// we crashed, so sessionstore.js has tabs from last time
|
||||
sessionFilename = "sessionstore.js";
|
||||
} else if (new File(profileDir, "sessionstore.bak").exists()) {
|
||||
// we did not crash, so previous session was moved to sessionstore.bak on quit
|
||||
sessionFilename = "sessionstore.bak";
|
||||
} else {
|
||||
// no previous session data
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// sessionstore init has occurred, so previous session will always
|
||||
// be in sessionstore.bak
|
||||
sessionFilename = "sessionstore.bak";
|
||||
String jsonString = GeckoApp.mAppContext.getProfile().readSessionFile(GeckoApp.sIsGeckoReady);
|
||||
if (jsonString == null) {
|
||||
// no previous session data
|
||||
return;
|
||||
}
|
||||
|
||||
final JSONArray tabs;
|
||||
String jsonString = readJSONFile(activity, sessionFilename);
|
||||
if (jsonString == null)
|
||||
return;
|
||||
|
||||
try {
|
||||
tabs = new JSONObject(jsonString).getJSONArray("windows")
|
||||
.getJSONObject(0)
|
||||
|
|
|
@ -125,7 +125,7 @@ abstract public class GeckoApp
|
|||
public static Menu sMenu;
|
||||
private static GeckoThread sGeckoThread = null;
|
||||
public GeckoAppHandler mMainHandler;
|
||||
private File mProfileDir;
|
||||
private GeckoProfile mProfile;
|
||||
public static boolean sIsGeckoReady = false;
|
||||
public static int mOrientation;
|
||||
|
||||
|
@ -849,21 +849,6 @@ abstract public class GeckoApp
|
|||
}
|
||||
}
|
||||
|
||||
public File getProfileDir() {
|
||||
return getProfileDir("default");
|
||||
}
|
||||
|
||||
public File getProfileDir(final String profileName) {
|
||||
if (mProfileDir != null)
|
||||
return mProfileDir;
|
||||
try {
|
||||
mProfileDir = GeckoDirProvider.getProfileDir(mAppContext, profileName);
|
||||
} catch (IOException ex) {
|
||||
Log.e(LOGTAG, "Error getting profile dir.", ex);
|
||||
}
|
||||
return mProfileDir;
|
||||
}
|
||||
|
||||
void addTab() {
|
||||
showAwesomebar(AwesomeBar.Type.ADD);
|
||||
}
|
||||
|
@ -1714,7 +1699,7 @@ abstract public class GeckoApp
|
|||
Pattern p = Pattern.compile("(?:-profile\\s*)(\\w*)(\\s*)");
|
||||
Matcher m = p.matcher(args);
|
||||
if (m.find()) {
|
||||
mProfileDir = new File(m.group(1));
|
||||
mProfile = GeckoProfile.get(this, m.group(1));
|
||||
mLastTitle = null;
|
||||
mLastViewport = null;
|
||||
mLastScreen = null;
|
||||
|
@ -1736,13 +1721,7 @@ abstract public class GeckoApp
|
|||
|
||||
if (passedUri == null || passedUri.equals("about:home")) {
|
||||
// show about:home if we aren't restoring previous session
|
||||
Log.w(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - start check sessionstore.js exists");
|
||||
File profileDir = getProfileDir();
|
||||
boolean sessionExists = false;
|
||||
if (profileDir != null)
|
||||
sessionExists = new File(profileDir, "sessionstore.js").exists();
|
||||
Log.w(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - finish check sessionstore.js exists");
|
||||
if (!sessionExists) {
|
||||
if (! getProfile().hasSession()) {
|
||||
mBrowserToolbar.updateTabCount(1);
|
||||
showAboutHome();
|
||||
}
|
||||
|
@ -1892,6 +1871,14 @@ abstract public class GeckoApp
|
|||
}, 50);
|
||||
}
|
||||
|
||||
public GeckoProfile getProfile() {
|
||||
// fall back to default profile if we didn't load a specific one
|
||||
if (mProfile == null) {
|
||||
mProfile = GeckoProfile.get(this);
|
||||
}
|
||||
return mProfile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable Android StrictMode checks (for supported OS versions).
|
||||
* http://developer.android.com/reference/android/os/StrictMode.html
|
||||
|
@ -2371,7 +2358,7 @@ abstract public class GeckoApp
|
|||
}
|
||||
|
||||
private void checkMigrateProfile() {
|
||||
File profileDir = getProfileDir();
|
||||
File profileDir = getProfile().getDir();
|
||||
long currentTime = SystemClock.uptimeMillis();
|
||||
|
||||
if (profileDir != null) {
|
||||
|
|
|
@ -46,7 +46,6 @@ import org.mozilla.gecko.gfx.LayerView;
|
|||
import java.io.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.nio.*;
|
||||
import java.nio.channels.*;
|
||||
import java.text.*;
|
||||
import java.util.*;
|
||||
import java.util.zip.*;
|
||||
|
@ -263,106 +262,15 @@ public class GeckoAppShell
|
|||
return sFreeSpace;
|
||||
}
|
||||
|
||||
static boolean moveFile(File inFile, File outFile)
|
||||
{
|
||||
Log.i(LOGTAG, "moving " + inFile + " to " + outFile);
|
||||
if (outFile.isDirectory())
|
||||
outFile = new File(outFile, inFile.getName());
|
||||
try {
|
||||
if (inFile.renameTo(outFile))
|
||||
return true;
|
||||
} catch (SecurityException se) {
|
||||
Log.w(LOGTAG, "error trying to rename file", se);
|
||||
}
|
||||
try {
|
||||
long lastModified = inFile.lastModified();
|
||||
outFile.createNewFile();
|
||||
// so copy it instead
|
||||
FileChannel inChannel = new FileInputStream(inFile).getChannel();
|
||||
FileChannel outChannel = new FileOutputStream(outFile).getChannel();
|
||||
long size = inChannel.size();
|
||||
long transferred = inChannel.transferTo(0, size, outChannel);
|
||||
inChannel.close();
|
||||
outChannel.close();
|
||||
outFile.setLastModified(lastModified);
|
||||
|
||||
if (transferred == size)
|
||||
inFile.delete();
|
||||
else
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "exception while moving file: ", e);
|
||||
try {
|
||||
outFile.delete();
|
||||
} catch (SecurityException se) {
|
||||
Log.w(LOGTAG, "error trying to delete file", se);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean moveDir(File from, File to) {
|
||||
try {
|
||||
to.mkdirs();
|
||||
if (from.renameTo(to))
|
||||
return true;
|
||||
} catch (SecurityException se) {
|
||||
Log.w(LOGTAG, "error trying to rename file", se);
|
||||
}
|
||||
File[] files = from.listFiles();
|
||||
boolean retVal = true;
|
||||
if (files == null)
|
||||
return false;
|
||||
try {
|
||||
Iterator<File> fileIterator = Arrays.asList(files).iterator();
|
||||
while (fileIterator.hasNext()) {
|
||||
File file = fileIterator.next();
|
||||
File dest = new File(to, file.getName());
|
||||
if (file.isDirectory())
|
||||
retVal = moveDir(file, dest) ? retVal : false;
|
||||
else
|
||||
retVal = moveFile(file, dest) ? retVal : false;
|
||||
}
|
||||
from.delete();
|
||||
} catch(Exception e) {
|
||||
Log.e(LOGTAG, "error trying to move file", e);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// java-side stuff
|
||||
public static boolean loadLibsSetup(String apkName) {
|
||||
// The package data lib directory isn't placed in ld.so's
|
||||
// search path, so we have to manually load libraries that
|
||||
// libxul will depend on. Not ideal.
|
||||
GeckoApp geckoApp = GeckoApp.mAppContext;
|
||||
String homeDir;
|
||||
sHomeDir = GeckoDirProvider.getFilesDir(geckoApp);
|
||||
homeDir = sHomeDir.getPath();
|
||||
GeckoProfile profile = geckoApp.getProfile();
|
||||
profile.moveProfilesToAppInstallLocation();
|
||||
|
||||
// handle the application being moved to phone from sdcard
|
||||
File profileDir = new File(homeDir, "mozilla");
|
||||
File oldHome = new File("/data/data/" +
|
||||
GeckoApp.mAppContext.getPackageName() + "/mozilla");
|
||||
if (oldHome.exists())
|
||||
moveDir(oldHome, profileDir);
|
||||
|
||||
if (Build.VERSION.SDK_INT < 8 ||
|
||||
geckoApp.getApplication().getPackageResourcePath().startsWith("/data") ||
|
||||
geckoApp.getApplication().getPackageResourcePath().startsWith("/system")) {
|
||||
if (Build.VERSION.SDK_INT >= 8) {
|
||||
File extHome = geckoApp.getExternalFilesDir(null);
|
||||
File extProf = new File (extHome, "mozilla");
|
||||
if (extHome != null && extProf != null && extProf.exists())
|
||||
moveDir(extProf, profileDir);
|
||||
}
|
||||
} else {
|
||||
File intHome = geckoApp.getFilesDir();
|
||||
File intProf = new File(intHome, "mozilla");
|
||||
if (intHome != null && intProf != null && intProf.exists())
|
||||
moveDir(intProf, profileDir);
|
||||
}
|
||||
try {
|
||||
String[] dirs = GeckoApp.mAppContext.getPluginDirectories();
|
||||
StringBuffer pluginSearchPath = new StringBuffer();
|
||||
|
@ -376,7 +284,7 @@ public class GeckoAppShell
|
|||
Log.i(LOGTAG, "exception getting plugin dirs", ex);
|
||||
}
|
||||
|
||||
GeckoAppShell.putenv("HOME=" + homeDir);
|
||||
GeckoAppShell.putenv("HOME=" + profile.getFilesDir().getPath());
|
||||
GeckoAppShell.putenv("GRE_HOME=" + GeckoApp.sGREDir.getPath());
|
||||
Intent i = geckoApp.getIntent();
|
||||
String env = i.getStringExtra("env0");
|
||||
|
|
|
@ -1,215 +0,0 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Android code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009-2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Wes Johnston <wjohnston@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.lang.Void;
|
||||
import java.util.Date;
|
||||
import java.util.Random;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
abstract public class GeckoDirProvider
|
||||
{
|
||||
private static final String LOGTAG = "GeckoDirProvider";
|
||||
private static HashMap<String, File> mProfileDirs = new HashMap<String, File>();
|
||||
|
||||
/**
|
||||
* Get the default Mozilla profile directory for a given Activity instance.
|
||||
*
|
||||
* @param aContext
|
||||
* The context for the activity. Must not be null
|
||||
* @return
|
||||
* The profile directory.
|
||||
*/
|
||||
static public File getProfileDir(final Context aContext)
|
||||
throws IllegalArgumentException, IOException {
|
||||
// XXX: TO-DO read profiles.ini to get the default profile. bug 71530
|
||||
return getProfileDir(aContext, "default");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a particular profile directory for a given Activity.
|
||||
* If no profile directory currently exists, will create and return a profile directory.
|
||||
* Otherwise will return null;
|
||||
*
|
||||
* @param aContext
|
||||
* The context for the Activity we want a profile for. Must not be null.
|
||||
* @param aProfileName
|
||||
* The name of the profile to open. Must be a non-empty string
|
||||
* @return
|
||||
* The profile directory.
|
||||
*/
|
||||
static public File getProfileDir(final Context aContext, final String aProfileName)
|
||||
throws IllegalArgumentException, IOException {
|
||||
|
||||
if (aContext == null)
|
||||
throw new IllegalArgumentException("Must provide a valid context");
|
||||
|
||||
if (aProfileName == null || aProfileName.trim().equals(""))
|
||||
throw new IllegalArgumentException("Profile name: '" + aProfileName + "' is not valid");
|
||||
|
||||
Log.i(LOGTAG, "Get profile dir for " + aProfileName);
|
||||
synchronized (mProfileDirs) {
|
||||
File profileDir = mProfileDirs.get(aProfileName);
|
||||
if (profileDir != null)
|
||||
return profileDir;
|
||||
|
||||
// we do not want to call File.exists on startup, so we first don't
|
||||
// attempt to create the mozilla directory.
|
||||
File mozDir = GeckoDirProvider.ensureMozillaDirectory(aContext);
|
||||
profileDir = GeckoDirProvider.getProfileDir(mozDir, aProfileName);
|
||||
|
||||
if (profileDir == null) {
|
||||
// Throws if cannot create.
|
||||
profileDir = GeckoDirProvider.createProfileDir(mozDir, aProfileName);
|
||||
}
|
||||
mProfileDirs.put(aProfileName, profileDir);
|
||||
return profileDir;
|
||||
}
|
||||
}
|
||||
|
||||
private static File getProfileDir(final File aRoot, final String aProfileName)
|
||||
throws IllegalArgumentException {
|
||||
if (aRoot == null)
|
||||
throw new IllegalArgumentException("Invalid root directory");
|
||||
|
||||
File[] profiles = aRoot.listFiles(new FileFilter() {
|
||||
public boolean accept(File pathname) {
|
||||
return pathname.getName().endsWith("." + aProfileName);
|
||||
}
|
||||
});
|
||||
|
||||
if (profiles != null && profiles.length > 0)
|
||||
return profiles[0];
|
||||
return null;
|
||||
}
|
||||
|
||||
private static File ensureMozillaDirectory(final Context aContext)
|
||||
throws IOException, IllegalArgumentException {
|
||||
if (aContext == null)
|
||||
throw new IllegalArgumentException("Must provide a valid context");
|
||||
File filesDir = GeckoDirProvider.getFilesDir(aContext);
|
||||
|
||||
File mozDir = new File(filesDir, "mozilla");
|
||||
if (!mozDir.exists()) {
|
||||
if (!mozDir.mkdir())
|
||||
throw new IOException("Unable to create mozilla directory at " + mozDir.getPath());
|
||||
}
|
||||
return mozDir;
|
||||
}
|
||||
|
||||
static final char kTable[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
|
||||
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };
|
||||
|
||||
private static File createProfileDir(final File aRootDir, final String aProfileName)
|
||||
throws IOException, IllegalArgumentException {
|
||||
|
||||
if (aRootDir == null)
|
||||
throw new IllegalArgumentException("Must provide a valid root directory");
|
||||
|
||||
if (aProfileName == null || aProfileName.trim().equals(""))
|
||||
throw new IllegalArgumentException("Profile name: '" + aProfileName + "' is not valid");
|
||||
|
||||
// XXX: TO-DO If we already have an ini file, we should append the
|
||||
// new profile information to it. For now we just throw an exception.
|
||||
// see bug 715391
|
||||
final File profileIni = new File(aRootDir, "profiles.ini");
|
||||
if (profileIni.exists())
|
||||
throw new IOException("Can't create new profiles");
|
||||
|
||||
String saltedName = saltProfileName(aProfileName);
|
||||
File profile = new File(aRootDir, saltedName);
|
||||
while (profile.exists()) {
|
||||
saltedName = saltProfileName(aProfileName);
|
||||
profile = new File(aRootDir, saltedName);
|
||||
}
|
||||
|
||||
if (!profile.mkdir())
|
||||
throw new IOException("Unable to create profile at " + profile.getPath());
|
||||
|
||||
Log.i(LOGTAG, "Creating new profile at " + profile.getPath());
|
||||
final String fSaltedName = saltedName;
|
||||
|
||||
FileWriter outputStream = new FileWriter(profileIni, true);
|
||||
outputStream.write("[General]\n" +
|
||||
"StartWithLastProfile=1\n" +
|
||||
"\n" +
|
||||
"[Profile0]\n" +
|
||||
"Name=" + aProfileName + "\n" +
|
||||
"IsRelative=1\n" +
|
||||
"Path=" + fSaltedName + "\n" +
|
||||
"Default=1\n");
|
||||
outputStream.close();
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
private static String saltProfileName(final String aName) {
|
||||
Random randomGenerator = new Random(System.nanoTime());
|
||||
|
||||
StringBuilder salt = new StringBuilder();
|
||||
int i;
|
||||
for (i = 0; i < 8; ++i)
|
||||
salt.append(kTable[randomGenerator.nextInt(kTable.length)]);
|
||||
|
||||
salt.append(".");
|
||||
return salt.append(aName).toString();
|
||||
}
|
||||
|
||||
public static File getFilesDir(final Context aContext) {
|
||||
if (aContext == null)
|
||||
throw new IllegalArgumentException("Must provide a valid context");
|
||||
|
||||
if (Build.VERSION.SDK_INT < 8 ||
|
||||
aContext.getPackageResourcePath().startsWith("/data") ||
|
||||
aContext.getPackageResourcePath().startsWith("/system")) {
|
||||
return aContext.getFilesDir();
|
||||
}
|
||||
return aContext.getExternalFilesDir(null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,356 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.HashMap;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.SystemClock;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
public final class GeckoProfile {
|
||||
private static final String LOGTAG = "GeckoProfile";
|
||||
|
||||
private static HashMap<String, GeckoProfile> sProfileCache = new HashMap<String, GeckoProfile>();
|
||||
|
||||
private final Context mContext;
|
||||
private final String mName;
|
||||
private File mMozDir;
|
||||
private File mDir;
|
||||
|
||||
public static GeckoProfile get(Context context) {
|
||||
return get(context, null);
|
||||
}
|
||||
|
||||
public static GeckoProfile get(Context context, String profileName) {
|
||||
if (context == null) {
|
||||
throw new IllegalArgumentException("context must be non-null");
|
||||
}
|
||||
if (TextUtils.isEmpty(profileName)) {
|
||||
// XXX: TO-DO read profiles.ini to get the default profile. bug 715307
|
||||
profileName = "default";
|
||||
}
|
||||
|
||||
synchronized (sProfileCache) {
|
||||
GeckoProfile profile = sProfileCache.get(profileName);
|
||||
if (profile == null) {
|
||||
profile = new GeckoProfile(context, profileName);
|
||||
sProfileCache.put(profileName, profile);
|
||||
}
|
||||
return profile;
|
||||
}
|
||||
}
|
||||
|
||||
private GeckoProfile(Context context, String profileName) {
|
||||
mContext = context;
|
||||
mName = profileName;
|
||||
}
|
||||
|
||||
public File getDir() {
|
||||
if (mDir != null) {
|
||||
return mDir;
|
||||
}
|
||||
|
||||
try {
|
||||
File mozillaDir = ensureMozillaDirectory();
|
||||
mDir = findProfileDir(mozillaDir);
|
||||
if (mDir == null) {
|
||||
mDir = createProfileDir(mozillaDir);
|
||||
} else {
|
||||
Log.d(LOGTAG, "Found profile dir: " + mDir.getAbsolutePath());
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
Log.e(LOGTAG, "Error getting profile dir", ioe);
|
||||
}
|
||||
return mDir;
|
||||
}
|
||||
|
||||
public boolean hasSession() {
|
||||
Log.w(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - start check sessionstore.js exists");
|
||||
File dir = getDir();
|
||||
boolean hasSession = (dir != null && new File(dir, "sessionstore.js").exists());
|
||||
Log.w(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - finish check sessionstore.js exists");
|
||||
return hasSession;
|
||||
}
|
||||
|
||||
public String readSessionFile(boolean geckoReady) {
|
||||
File dir = getDir();
|
||||
if (dir == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
File sessionFile = null;
|
||||
if (! geckoReady) {
|
||||
// we might have crashed, in which case sessionstore.js has tabs from last time
|
||||
sessionFile = new File(dir, "sessionstore.js");
|
||||
if (! sessionFile.exists()) {
|
||||
sessionFile = null;
|
||||
}
|
||||
}
|
||||
if (sessionFile == null) {
|
||||
// either we did not crash, so previous session was moved to sessionstore.bak on quit,
|
||||
// or sessionstore init has occurred, so previous session will always
|
||||
// be in sessionstore.bak
|
||||
sessionFile = new File(dir, "sessionstore.bak");
|
||||
// no need to check if the session file exists here; readFile will throw
|
||||
// an IOException if it does not
|
||||
}
|
||||
|
||||
try {
|
||||
return readFile(sessionFile);
|
||||
} catch (IOException ioe) {
|
||||
Log.i(LOGTAG, "Unable to read session file " + sessionFile.getAbsolutePath());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String readFile(String filename) throws IOException {
|
||||
File dir = getDir();
|
||||
if (dir == null) {
|
||||
throw new IOException("No profile directory found");
|
||||
}
|
||||
File target = new File(dir, filename);
|
||||
return readFile(target);
|
||||
}
|
||||
|
||||
private String readFile(File target) throws IOException {
|
||||
FileReader fr = new FileReader(target);
|
||||
try {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
char[] buf = new char[8192];
|
||||
int read = fr.read(buf);
|
||||
while (read >= 0) {
|
||||
sb.append(buf, 0, read);
|
||||
read = fr.read(buf);
|
||||
}
|
||||
return sb.toString();
|
||||
} finally {
|
||||
fr.close();
|
||||
}
|
||||
}
|
||||
|
||||
public File getFilesDir() {
|
||||
if (isOnInternalStorage()) {
|
||||
return mContext.getFilesDir();
|
||||
} else {
|
||||
return mContext.getExternalFilesDir(null);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isOnInternalStorage() {
|
||||
// prior to version 8, apps were always on internal storage
|
||||
if (Build.VERSION.SDK_INT < 8) {
|
||||
return true;
|
||||
}
|
||||
// otherwise, check app install location to see if it is on internal storage
|
||||
String resourcePath = mContext.getPackageResourcePath();
|
||||
if (resourcePath.startsWith("/data") || resourcePath.startsWith("/system")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// otherwise we're most likely on external storage
|
||||
return false;
|
||||
}
|
||||
|
||||
public void moveProfilesToAppInstallLocation() {
|
||||
// check normal install directory
|
||||
moveProfilesFrom(new File("/data/data/" + mContext.getPackageName()));
|
||||
|
||||
if (isOnInternalStorage()) {
|
||||
if (Build.VERSION.SDK_INT >= 8) {
|
||||
// if we're currently on internal storage, but we're on API >= 8, so it's possible that
|
||||
// we were previously on external storage, check there for profiles to pull in
|
||||
moveProfilesFrom(mContext.getExternalFilesDir(null));
|
||||
}
|
||||
} else {
|
||||
// we're currently on external storage, but could have been on internal storage previously,
|
||||
// so pull in those profiles
|
||||
moveProfilesFrom(mContext.getFilesDir());
|
||||
}
|
||||
}
|
||||
|
||||
private void moveProfilesFrom(File oldFilesDir) {
|
||||
if (oldFilesDir == null) {
|
||||
return;
|
||||
}
|
||||
File oldMozDir = new File(oldFilesDir, "mozilla");
|
||||
if (! (oldMozDir.exists() && oldMozDir.isDirectory())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if we get here, we know that oldMozDir exists
|
||||
|
||||
File currentMozDir;
|
||||
try {
|
||||
currentMozDir = ensureMozillaDirectory();
|
||||
if (currentMozDir.equals(oldMozDir)) {
|
||||
return;
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
Log.e(LOGTAG, "Unable to create a profile directory!", ioe);
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d(LOGTAG, "Moving old profile directories from " + oldMozDir.getAbsolutePath());
|
||||
|
||||
// if we get here, we know that oldMozDir != currentMozDir, so we have some stuff to move
|
||||
moveDirContents(oldMozDir, currentMozDir);
|
||||
}
|
||||
|
||||
private void moveDirContents(File src, File dst) {
|
||||
File[] files = src.listFiles();
|
||||
if (files == null) {
|
||||
src.delete();
|
||||
return;
|
||||
}
|
||||
for (File f : files) {
|
||||
File target = new File(dst, f.getName());
|
||||
try {
|
||||
if (f.renameTo(target)) {
|
||||
continue;
|
||||
}
|
||||
} catch (SecurityException se) {
|
||||
Log.e(LOGTAG, "Unable to rename file to " + target.getAbsolutePath() + " while moving profiles", se);
|
||||
}
|
||||
// rename failed, try moving manually
|
||||
if (f.isDirectory()) {
|
||||
if (target.mkdirs()) {
|
||||
moveDirContents(f, target);
|
||||
} else {
|
||||
Log.e(LOGTAG, "Unable to create folder " + target.getAbsolutePath() + " while moving profiles");
|
||||
}
|
||||
} else {
|
||||
if (! moveFile(f, target)) {
|
||||
Log.e(LOGTAG, "Unable to move file " + target.getAbsolutePath() + " while moving profiles");
|
||||
}
|
||||
}
|
||||
}
|
||||
src.delete();
|
||||
}
|
||||
|
||||
private boolean moveFile(File src, File dst) {
|
||||
boolean success = false;
|
||||
long lastModified = src.lastModified();
|
||||
try {
|
||||
FileInputStream fis = new FileInputStream(src);
|
||||
try {
|
||||
FileOutputStream fos = new FileOutputStream(dst);
|
||||
try {
|
||||
FileChannel inChannel = fis.getChannel();
|
||||
long size = inChannel.size();
|
||||
if (size == inChannel.transferTo(0, size, fos.getChannel())) {
|
||||
success = true;
|
||||
}
|
||||
} finally {
|
||||
fos.close();
|
||||
}
|
||||
} finally {
|
||||
fis.close();
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
Log.e(LOGTAG, "Exception while attempting to move file to " + dst.getAbsolutePath(), ioe);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
dst.setLastModified(lastModified);
|
||||
src.delete();
|
||||
} else {
|
||||
dst.delete();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
private File ensureMozillaDirectory() throws IOException {
|
||||
if (mMozDir != null) {
|
||||
return mMozDir;
|
||||
}
|
||||
|
||||
File filesDir = getFilesDir();
|
||||
File mozDir = new File(filesDir, "mozilla");
|
||||
if (! mozDir.exists()) {
|
||||
if (! mozDir.mkdirs()) {
|
||||
throw new IOException("Unable to create mozilla directory at " + mozDir.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
mMozDir = mozDir;
|
||||
return mMozDir;
|
||||
}
|
||||
|
||||
private File findProfileDir(File mozillaDir) {
|
||||
String suffix = '.' + mName;
|
||||
File[] candidates = mozillaDir.listFiles();
|
||||
if (candidates == null) {
|
||||
return null;
|
||||
}
|
||||
for (File f : candidates) {
|
||||
if (f.isDirectory() && f.getName().endsWith(suffix)) {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String saltProfileName(String name) {
|
||||
String allowedChars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
StringBuffer salt = new StringBuffer(16);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
salt.append(allowedChars.charAt((int)(Math.random() * allowedChars.length())));
|
||||
}
|
||||
salt.append('.');
|
||||
salt.append(name);
|
||||
return salt.toString();
|
||||
}
|
||||
|
||||
private File createProfileDir(File mozillaDir) throws IOException {
|
||||
// XXX: TO-DO If we already have an ini file, we should append the
|
||||
// new profile information to it. For now we just throw an exception.
|
||||
// see bug 715391
|
||||
File profileIniFile = new File(mozillaDir, "profiles.ini");
|
||||
if (profileIniFile.exists()) {
|
||||
throw new IOException("Can't create new profiles");
|
||||
}
|
||||
|
||||
String saltedName = saltProfileName(mName);
|
||||
File profileDir = new File(mozillaDir, saltedName);
|
||||
while (profileDir.exists()) {
|
||||
saltedName = saltProfileName(mName);
|
||||
profileDir = new File(mozillaDir, saltedName);
|
||||
}
|
||||
|
||||
if (! profileDir.mkdirs()) {
|
||||
throw new IOException("Unable to create profile at " + profileDir.getAbsolutePath());
|
||||
}
|
||||
Log.d(LOGTAG, "Created new profile dir at " + profileDir.getAbsolutePath());
|
||||
|
||||
FileWriter out = new FileWriter(profileIniFile, true);
|
||||
try {
|
||||
out.write("[General]\n" +
|
||||
"StartWithLastProfile=1\n" +
|
||||
"\n" +
|
||||
"[Profile0]\n" +
|
||||
"Name=" + mName + "\n" +
|
||||
"IsRelative=1\n" +
|
||||
"Path=" + saltedName + "\n" +
|
||||
"Default=1\n");
|
||||
} finally {
|
||||
out.close();
|
||||
}
|
||||
|
||||
return profileDir;
|
||||
}
|
||||
}
|
|
@ -147,47 +147,15 @@ public class LauncherShortcuts extends Activity {
|
|||
mWebappsList = null;
|
||||
|
||||
Context context = getApplicationContext();
|
||||
|
||||
File home = new File(context.getFilesDir(), "mozilla");
|
||||
if (!home.exists())
|
||||
home = new File(context.getExternalFilesDir(null).getPath(), "mozilla");
|
||||
|
||||
if (!home.exists())
|
||||
return null;
|
||||
|
||||
File profile = null;
|
||||
String[] files = home.list();
|
||||
for (String file : files) {
|
||||
if (file.endsWith(".default")) {
|
||||
profile = new File(home, file);
|
||||
break;
|
||||
}
|
||||
GeckoProfile profile = GeckoProfile.get(context);
|
||||
String webappsJson = null;
|
||||
try {
|
||||
webappsJson = profile.readFile("webapps" + File.separatorChar + "webapps.json");
|
||||
} catch (IOException ioe) {
|
||||
// unable to load the file, leave webappsJson as null
|
||||
}
|
||||
|
||||
if (profile == null)
|
||||
return null;
|
||||
|
||||
// Save the folder path to be used during click event
|
||||
mWebappsFolder = new File(profile, "webapps");
|
||||
if (!mWebappsFolder.exists())
|
||||
return null;
|
||||
|
||||
File webapps = new File(mWebappsFolder, "webapps.json");
|
||||
if (!webapps.exists())
|
||||
return null;
|
||||
|
||||
// Parse the contents into a string
|
||||
String webappsJson = new String();
|
||||
try {
|
||||
BufferedReader in = new BufferedReader(new FileReader(webapps));
|
||||
String line = new String();
|
||||
|
||||
while ((line = in.readLine()) != null) {
|
||||
webappsJson += line;
|
||||
}
|
||||
} catch (IOException e) { }
|
||||
|
||||
if (webappsJson.length() == 0)
|
||||
if (TextUtils.isEmpty(webappsJson))
|
||||
return null;
|
||||
|
||||
mWebappsList = new ArrayList<HashMap<String, String>>();
|
||||
|
|
|
@ -83,11 +83,11 @@ FENNEC_JAVA_FILES = \
|
|||
GeckoAsyncTask.java \
|
||||
GeckoBatteryManager.java \
|
||||
GeckoConnectivityReceiver.java \
|
||||
GeckoDirProvider.java \
|
||||
GeckoEvent.java \
|
||||
GeckoEventListener.java \
|
||||
GeckoInputConnection.java \
|
||||
GeckoPreferences.java \
|
||||
GeckoProfile.java \
|
||||
GeckoStateListDrawable.java \
|
||||
GeckoThread.java \
|
||||
GlobalHistory.java \
|
||||
|
|
|
@ -48,7 +48,7 @@ import java.util.List;
|
|||
import java.util.Random;
|
||||
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoDirProvider;
|
||||
import org.mozilla.gecko.GeckoProfile;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.db.BrowserContract.Bookmarks;
|
||||
import org.mozilla.gecko.db.BrowserContract.CommonColumns;
|
||||
|
@ -654,13 +654,7 @@ public class BrowserProvider extends ContentProvider {
|
|||
return "browser-" + profile + ".db";
|
||||
}
|
||||
|
||||
File profileDir = null;
|
||||
try {
|
||||
profileDir = GeckoDirProvider.getProfileDir(mContext, profile);
|
||||
} catch (IOException ex) {
|
||||
Log.e(LOGTAG, "Error getting profile dir", ex);
|
||||
}
|
||||
|
||||
File profileDir = GeckoProfile.get(mContext, profile).getDir();
|
||||
if (profileDir == null) {
|
||||
debug("Couldn't find directory for profile: " + profile);
|
||||
return null;
|
||||
|
@ -754,7 +748,7 @@ public class BrowserProvider extends ContentProvider {
|
|||
public void run() {
|
||||
// Kick this off early. It is synchronized so that other callers will wait
|
||||
try {
|
||||
GeckoDirProvider.getProfileDir(getContext());
|
||||
GeckoProfile.get(getContext()).getDir();
|
||||
} catch (Exception ex) {
|
||||
Log.e(LOGTAG, "Error getting profile dir", ex);
|
||||
}
|
||||
|
|
|
@ -14,9 +14,9 @@ import java.util.Random;
|
|||
|
||||
import org.mozilla.gecko.GeckoApp;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoDirProvider;
|
||||
import org.mozilla.gecko.GeckoEvent;
|
||||
import org.mozilla.gecko.GeckoEventListener;
|
||||
import org.mozilla.gecko.GeckoProfile;
|
||||
import org.mozilla.gecko.db.BrowserContract.CommonColumns;
|
||||
import org.mozilla.gecko.db.DBUtils;
|
||||
import org.mozilla.gecko.db.BrowserContract.Passwords;
|
||||
|
@ -162,13 +162,7 @@ public class PasswordsProvider extends ContentProvider {
|
|||
}
|
||||
|
||||
private String getDatabasePath(String profile) {
|
||||
File profileDir = null;
|
||||
try {
|
||||
profileDir = GeckoDirProvider.getProfileDir(mContext, profile);
|
||||
} catch (IOException ex) {
|
||||
Log.e(LOGTAG, "Error getting profile dir", ex);
|
||||
}
|
||||
|
||||
File profileDir = GeckoProfile.get(mContext, profile).getDir();
|
||||
if (profileDir == null) {
|
||||
Log.d(LOGTAG, "Couldn't find directory for profile: " + profile);
|
||||
return null;
|
||||
|
|
Загрузка…
Ссылка в новой задаче