/**
   * Discover the default profile name by examining profiles.ini.
   *
   * <p>Package-scoped because {@link GeckoProfile} needs access to it.
   *
   * @return null if there is no "Default" entry in profiles.ini, or the profile name if there is.
   * @throws NoMozillaDirectoryException if the Mozilla directory did not exist and could not be
   *     created.
   */
  static String findDefaultProfileName(final Context context) throws NoMozillaDirectoryException {
    final INIParser parser = GeckoProfileDirectories.getProfilesINI(getMozillaDirectory(context));

    for (Enumeration<INISection> e = parser.getSections().elements(); e.hasMoreElements(); ) {
      final INISection section = e.nextElement();
      if (section.getIntProperty("Default") == 1) {
        return section.getStringProperty("Name");
      }
    }

    return null;
  }
  public static File findProfileDir(final File mozillaDir, final String profileName)
      throws NoSuchProfileException {
    // Open profiles.ini to find the correct path.
    final INIParser parser = GeckoProfileDirectories.getProfilesINI(mozillaDir);

    for (Enumeration<INISection> e = parser.getSections().elements(); e.hasMoreElements(); ) {
      final INISection section = e.nextElement();
      final String name = section.getStringProperty("Name");
      if (name != null && name.equals(profileName)) {
        if (section.getIntProperty("IsRelative") == 1) {
          return new File(mozillaDir, section.getStringProperty("Path"));
        }
        return new File(section.getStringProperty("Path"));
      }
    }

    throw new NoSuchProfileException("No profile " + profileName);
  }
  /**
   * Return a mapping from the names of all matching profiles (that is, profiles appearing in
   * profiles.ini that match the supplied predicate) to their absolute paths on disk.
   *
   * @param mozillaDir a directory containing profiles.ini.
   * @param predicate a predicate to use when evaluating whether to include a particular INI
   *     section.
   * @param stopOnSuccess if true, this method will return with the first result that matches the
   *     predicate; if false, all matching results are included.
   * @return a {@link Map} from name to path.
   */
  public static Map<String, String> getMatchingProfiles(
      final File mozillaDir, INISectionPredicate predicate, boolean stopOnSuccess) {
    final HashMap<String, String> result = new HashMap<String, String>();
    final INIParser parser = GeckoProfileDirectories.getProfilesINI(mozillaDir);

    for (Enumeration<INISection> e = parser.getSections().elements(); e.hasMoreElements(); ) {
      final INISection section = e.nextElement();
      if (predicate == null || predicate.matches(section)) {
        final String name = section.getStringProperty("Name");
        final String pathString = section.getStringProperty("Path");
        final boolean isRelative = section.getIntProperty("IsRelative") == 1;
        final File path = isRelative ? new File(mozillaDir, pathString) : new File(pathString);
        result.put(name, path.getAbsolutePath());

        if (stopOnSuccess) {
          return result;
        }
      }
    }
    return result;
  }
示例#4
0
  private File createProfileDir() throws IOException {
    INIParser parser = GeckoProfileDirectories.getProfilesINI(mMozillaDir);

    // Salt the name of our requested profile
    String saltedName = GeckoProfileDirectories.saltProfileName(mName);
    File profileDir = new File(mMozillaDir, saltedName);
    while (profileDir.exists()) {
      saltedName = GeckoProfileDirectories.saltProfileName(mName);
      profileDir = new File(mMozillaDir, saltedName);
    }

    // Attempt to create the salted profile dir
    if (!profileDir.mkdirs()) {
      throw new IOException("Unable to create profile.");
    }
    Log.d(LOGTAG, "Created new profile dir.");

    // Now update profiles.ini
    // If this is the first time its created, we also add a General section
    // look for the first profile number that isn't taken yet
    int profileNum = 0;
    boolean isDefaultSet = false;
    INISection profileSection;
    while ((profileSection = parser.getSection("Profile" + profileNum)) != null) {
      profileNum++;
      if (profileSection.getProperty("Default") != null) {
        isDefaultSet = true;
      }
    }

    profileSection = new INISection("Profile" + profileNum);
    profileSection.setProperty("Name", mName);
    profileSection.setProperty("IsRelative", 1);
    profileSection.setProperty("Path", saltedName);

    if (parser.getSection("General") == null) {
      INISection generalSection = new INISection("General");
      generalSection.setProperty("StartWithLastProfile", 1);
      parser.addSection(generalSection);
    }

    if (!isDefaultSet && !mIsWebAppProfile) {
      // only set as default if this is the first non-webapp
      // profile we're creating
      profileSection.setProperty("Default", 1);

      // We have no intention of stopping this session. The FIRSTRUN session
      // ends when the browsing session/activity has ended. All events
      // during firstrun will be tagged as FIRSTRUN.
      Telemetry.startUISession(TelemetryContract.Session.FIRSTRUN);
    }

    parser.addSection(profileSection);
    parser.write();

    // Trigger init for non-webapp profiles.
    if (!mIsWebAppProfile) {
      enqueueInitialization();
    }

    // Write out profile creation time, mirroring the logic in nsToolkitProfileService.
    try {
      FileOutputStream stream =
          new FileOutputStream(profileDir.getAbsolutePath() + File.separator + "times.json");
      OutputStreamWriter writer = new OutputStreamWriter(stream, Charset.forName("UTF-8"));
      try {
        writer.append("{\"created\": " + System.currentTimeMillis() + "}\n");
      } finally {
        writer.close();
      }
    } catch (Exception e) {
      // Best-effort.
      Log.w(LOGTAG, "Couldn't write times.json.", e);
    }

    // Initialize pref flag for displaying the start pane for a new non-webapp profile.
    if (!mIsWebAppProfile) {
      final SharedPreferences prefs = GeckoSharedPrefs.forProfile(mApplicationContext);
      prefs.edit().putBoolean(BrowserApp.PREF_STARTPANE_ENABLED, true).apply();
    }

    return profileDir;
  }
示例#5
0
  private boolean remove() {
    try {
      synchronized (this) {
        final File dir = getDir();
        if (dir.exists()) {
          delete(dir);
        }

        try {
          mProfileDir = findProfileDir();
        } catch (NoSuchProfileException noSuchProfile) {
          // If the profile doesn't exist, there's nothing left for us to do.
          return false;
        }
      }

      final INIParser parser = GeckoProfileDirectories.getProfilesINI(mMozillaDir);
      final Hashtable<String, INISection> sections = parser.getSections();
      for (Enumeration<INISection> e = sections.elements(); e.hasMoreElements(); ) {
        final INISection section = e.nextElement();
        String name = section.getStringProperty("Name");

        if (name == null || !name.equals(mName)) {
          continue;
        }

        if (section.getName().startsWith("Profile")) {
          // ok, we have stupid Profile#-named things.  Rename backwards.
          try {
            int sectionNumber = Integer.parseInt(section.getName().substring("Profile".length()));
            String curSection = "Profile" + sectionNumber;
            String nextSection = "Profile" + (sectionNumber + 1);

            sections.remove(curSection);

            while (sections.containsKey(nextSection)) {
              parser.renameSection(nextSection, curSection);
              sectionNumber++;

              curSection = nextSection;
              nextSection = "Profile" + (sectionNumber + 1);
            }
          } catch (NumberFormatException nex) {
            // uhm, malformed Profile thing; we can't do much.
            Log.e(LOGTAG, "Malformed section name in profiles.ini: " + section.getName());
            return false;
          }
        } else {
          // this really shouldn't be the case, but handle it anyway
          parser.removeSection(mName);
        }

        break;
      }

      parser.write();
      return true;
    } catch (IOException ex) {
      Log.w(LOGTAG, "Failed to remove profile.", ex);
      return false;
    }
  }