/**
   * Update prefs that depend on home panels state.
   *
   * <p>This includes the prefs that keep track of whether bookmarks or history are enabled, which
   * are used to control the visibility of the corresponding menu items.
   */
  private void updatePrefsFromConfig(JSONArray panelsArray) {
    final SharedPreferences prefs = GeckoSharedPrefs.forProfile(mContext);
    if (!prefs.contains(HomeConfig.PREF_KEY_BOOKMARKS_PANEL_ENABLED)
        || !prefs.contains(HomeConfig.PREF_KEY_HISTORY_PANEL_ENABLED)) {

      final String bookmarkType = PanelType.BOOKMARKS.toString();
      final String historyType = PanelType.COMBINED_HISTORY.toString();
      try {
        for (int i = 0; i < panelsArray.length(); i++) {
          final JSONObject panelObj = panelsArray.getJSONObject(i);
          final String panelType = panelObj.optString(PanelConfig.JSON_KEY_TYPE, null);
          if (panelType == null) {
            break;
          }
          final boolean isDisabled = panelObj.optBoolean(PanelConfig.JSON_KEY_DISABLED, false);
          if (bookmarkType.equals(panelType)) {
            prefs
                .edit()
                .putBoolean(HomeConfig.PREF_KEY_BOOKMARKS_PANEL_ENABLED, !isDisabled)
                .apply();
          } else if (historyType.equals(panelType)) {
            prefs.edit().putBoolean(HomeConfig.PREF_KEY_HISTORY_PANEL_ENABLED, !isDisabled).apply();
          }
        }
      } catch (JSONException e) {
        Log.e(LOGTAG, "Error fetching panel from config to update prefs");
      }
    }
  }
    private void saveToPrefs() {
      GeckoSharedPrefs.forProfile(mApplication)
          .edit()
          .putString(PREFS_URL, mHeaderURL)
          .putString(PREFS_COLOR, mColor)
          .apply();

      // Let's keep the saved data in sync.
      mSavedURL = mHeaderURL;
      mSavedColor = mColor;
    }
  public CombinedHistoryAdapter(Context context, int savedParentIndex) {
    super();
    this.context = context;
    sectionHeaders = new SparseArray<>();

    // This races when multiple Fragments are created. That's okay: one
    // will win, and thereafter, all will be okay. If we create and then
    // drop an instance the shared SharedPreferences backing all the
    // instances will maintain the state for us. Since everything happens on
    // the UI thread, this doesn't even need to be volatile.
    if (sState == null) {
      sState = new RemoteTabsExpandableListState(GeckoSharedPrefs.forProfile(context));
    }
    remoteClientIndexOfParent = savedParentIndex;
  }
  public void testHiddenSites() {
    resources.setSuggestedSitesResource(generateSites(6));

    List<String> visibleUrls = new ArrayList<String>(3);
    visibleUrls.add("url3");
    visibleUrls.add("url4");
    visibleUrls.add("url5");

    List<String> hiddenUrls = new ArrayList<String>(3);
    hiddenUrls.add("url0");
    hiddenUrls.add("url1");
    hiddenUrls.add("url2");

    // Add mocked hidden sites to SharedPreferences.
    StringBuilder hiddenUrlBuilder = new StringBuilder();
    for (String s : hiddenUrls) {
      hiddenUrlBuilder.append(" ");
      hiddenUrlBuilder.append(Uri.encode(s));
    }

    final String hiddenPref = hiddenUrlBuilder.toString();
    GeckoSharedPrefs.forProfile(context)
        .edit()
        .putString(SuggestedSites.PREF_SUGGESTED_SITES_HIDDEN, hiddenPref)
        .commit();

    Cursor c = new SuggestedSites(context).get(DEFAULT_LIMIT);
    assertEquals(Math.min(3, DEFAULT_LIMIT), c.getCount());

    c.moveToPosition(-1);
    while (c.moveToNext()) {
      String url = c.getString(c.getColumnIndexOrThrow(BrowserContract.SuggestedSites.URL));
      assertFalse(hiddenUrls.contains(url));
      assertTrue(visibleUrls.contains(url));
    }

    c.close();
  }
Esempio n. 5
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;
  }
Esempio n. 6
0
 private SharedPreferences getSharedPreferences() {
   return GeckoSharedPrefs.forProfile(mContext);
 }
Esempio n. 7
0
  /**
   * Migrates JSON config data storage.
   *
   * @param context Context used to get shared preferences and create built-in panel.
   * @param jsonString String currently stored in preferences.
   * @return JSONArray array representing new set of panel configs.
   */
  private static synchronized JSONArray maybePerformMigration(Context context, String jsonString)
      throws JSONException {
    // If the migration is already done, we're at the current version.
    if (sMigrationDone) {
      final JSONObject json = new JSONObject(jsonString);
      return json.getJSONArray(JSON_KEY_PANELS);
    }

    // Make sure we only do this version check once.
    sMigrationDone = true;

    final JSONArray originalJsonPanels;
    final int version;

    final SharedPreferences prefs = GeckoSharedPrefs.forProfile(context);
    if (prefs.contains(PREFS_CONFIG_KEY_OLD)) {
      // Our original implementation did not contain versioning, so this is implicitly version 0.
      originalJsonPanels = new JSONArray(jsonString);
      version = 0;
    } else {
      final JSONObject json = new JSONObject(jsonString);
      originalJsonPanels = json.getJSONArray(JSON_KEY_PANELS);
      version = json.getInt(JSON_KEY_VERSION);
    }

    if (version == VERSION) {
      return originalJsonPanels;
    }

    Log.d(LOGTAG, "Performing migration");

    final JSONArray newJsonPanels = new JSONArray();
    final SharedPreferences.Editor prefsEditor = prefs.edit();

    for (int v = version + 1; v <= VERSION; v++) {
      Log.d(LOGTAG, "Migrating to version = " + v);

      switch (v) {
        case 1:
          // Add "Recent Tabs" panel
          final PanelConfig recentTabsConfig =
              createBuiltinPanelConfig(context, PanelType.RECENT_TABS);
          final JSONObject jsonRecentTabsConfig = recentTabsConfig.toJSON();

          // Add the new panel to the front of the array on phones.
          if (!HardwareUtils.isTablet()) {
            newJsonPanels.put(jsonRecentTabsConfig);
          }

          // Copy the original panel configs.
          final int count = originalJsonPanels.length();
          for (int i = 0; i < count; i++) {
            final JSONObject jsonPanelConfig = originalJsonPanels.getJSONObject(i);
            newJsonPanels.put(jsonPanelConfig);
          }

          // Add the new panel to the end of the array on tablets.
          if (HardwareUtils.isTablet()) {
            newJsonPanels.put(jsonRecentTabsConfig);
          }

          // Remove the old pref key.
          prefsEditor.remove(PREFS_CONFIG_KEY_OLD);
          break;
      }
    }

    // Save the new panel config and the new version number.
    final JSONObject newJson = new JSONObject();
    newJson.put(JSON_KEY_PANELS, newJsonPanels);
    newJson.put(JSON_KEY_VERSION, VERSION);

    prefsEditor.putString(PREFS_CONFIG_KEY, newJson.toString());
    prefsEditor.commit();

    return newJsonPanels;
  }
 private void loadFromPrefs() {
   SharedPreferences prefs = GeckoSharedPrefs.forProfile(mApplication);
   mSavedURL = prefs.getString(PREFS_URL, null);
   mSavedColor = prefs.getString(PREFS_COLOR, null);
 }
 /** Clear the data stored in preferences for fast path loading during startup */
 private void clearPrefs() {
   GeckoSharedPrefs.forProfile(mApplication).edit().remove(PREFS_URL).remove(PREFS_COLOR).apply();
 }
  /**
   * Migrates JSON config data storage.
   *
   * @param context Context used to get shared preferences and create built-in panel.
   * @param jsonString String currently stored in preferences.
   * @return JSONArray array representing new set of panel configs.
   */
  private static synchronized JSONArray maybePerformMigration(Context context, String jsonString)
      throws JSONException {
    // If the migration is already done, we're at the current version.
    if (sMigrationDone) {
      final JSONObject json = new JSONObject(jsonString);
      return json.getJSONArray(JSON_KEY_PANELS);
    }

    // Make sure we only do this version check once.
    sMigrationDone = true;

    JSONArray jsonPanels;
    final int version;

    final SharedPreferences prefs = GeckoSharedPrefs.forProfile(context);
    if (prefs.contains(PREFS_CONFIG_KEY_OLD)) {
      // Our original implementation did not contain versioning, so this is implicitly version 0.
      jsonPanels = new JSONArray(jsonString);
      version = 0;
    } else {
      final JSONObject json = new JSONObject(jsonString);
      jsonPanels = json.getJSONArray(JSON_KEY_PANELS);
      version = json.getInt(JSON_KEY_VERSION);
    }

    if (version == VERSION) {
      return jsonPanels;
    }

    Log.d(LOGTAG, "Performing migration");

    final SharedPreferences.Editor prefsEditor = prefs.edit();

    for (int v = version + 1; v <= VERSION; v++) {
      Log.d(LOGTAG, "Migrating to version = " + v);

      switch (v) {
        case 1:
          // Add "Recent Tabs" panel.
          addBuiltinPanelConfig(
              context, jsonPanels, PanelType.RECENT_TABS, Position.FRONT, Position.BACK);

          // Remove the old pref key.
          prefsEditor.remove(PREFS_CONFIG_KEY_OLD);
          break;

        case 2:
          // Add "Remote Tabs"/"Synced Tabs" panel.
          addBuiltinPanelConfig(
              context, jsonPanels, PanelType.DEPRECATED_REMOTE_TABS, Position.FRONT, Position.BACK);
          break;

        case 3:
          // Add the "Reading List" panel if it does not exist. At one time,
          // the Reading List panel was shown only to devices that were not
          // considered "low memory". Now, we expose the panel to all devices.
          // This migration should only occur for "low memory" devices.
          // Note: This will not agree with the default configuration, which
          // has DEPRECATED_REMOTE_TABS after READING_LIST on some devices.
          if (!readingListPanelExists(jsonPanels)) {
            addBuiltinPanelConfig(
                context, jsonPanels, PanelType.READING_LIST, Position.BACK, Position.BACK);
          }
          break;

        case 4:
          // Combine the History and Sync panels. In order to minimize an unexpected reordering
          // of panels, we try to replace the History panel if it's visible, and fall back to
          // the Sync panel if that's visible.
          jsonPanels = combineHistoryAndSyncPanels(context, jsonPanels);
          break;

        case 5:
          // This is the fix for bug 1264136 where we lost track of the default panel during some
          // migrations.
          ensureDefaultPanelForV5(context, jsonPanels);
          break;
      }
    }

    // Save the new panel config and the new version number.
    final JSONObject newJson = new JSONObject();
    newJson.put(JSON_KEY_PANELS, jsonPanels);
    newJson.put(JSON_KEY_VERSION, VERSION);

    prefsEditor.putString(PREFS_CONFIG_KEY, newJson.toString());
    prefsEditor.apply();

    return jsonPanels;
  }