Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / sync / android / java / src / org / chromium / sync / notifier / InvalidationPreferences.java
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.sync.notifier;
6
7 import android.accounts.Account;
8 import android.content.Context;
9 import android.content.SharedPreferences;
10 import android.preference.PreferenceManager;
11 import android.util.Base64;
12 import android.util.Log;
13
14 import com.google.common.annotations.VisibleForTesting;
15 import com.google.common.base.Preconditions;
16 import com.google.ipc.invalidation.external.client.types.ObjectId;
17
18 import java.util.Collection;
19 import java.util.HashSet;
20 import java.util.Set;
21
22 import javax.annotation.Nullable;
23
24 /**
25  * Class to manage the preferences used by the invalidation client.
26  * <p>
27  * This class provides methods to read and write the preferences used by the invalidation client.
28  * <p>
29  * To read a preference, call the appropriate {@code get...} method.
30  * <p>
31  * To write a preference, first call {@link #edit} to obtain a {@link EditContext}. Then, make
32  * one or more calls to a {@code set...} method, providing the same edit context to each call.
33  * Finally, call {@link #commit(EditContext)} to save the changes to stable storage.
34  *
35  * @author dsmyers@google.com (Daniel Myers)
36  */
37 public class InvalidationPreferences {
38     /**
39      * Wrapper around a {@link android.content.SharedPreferences.Editor} for the preferences.
40      * Used to avoid exposing raw preference objects to users of this class.
41      */
42     public class EditContext {
43         private final SharedPreferences.Editor mEditor;
44
45         EditContext() {
46             mEditor = PreferenceManager.getDefaultSharedPreferences(mContext).edit();
47         }
48     }
49
50     @VisibleForTesting
51     public static class PrefKeys {
52         /**
53          * Shared preference key to store the invalidation types that we want to register
54          * for.
55          */
56         @VisibleForTesting
57         public static final String SYNC_TANGO_TYPES = "sync_tango_types";
58
59         /**
60          * Shared preference key to store tango object ids for additional objects that we want to
61          * register for.
62          */
63         @VisibleForTesting
64         public static final String TANGO_OBJECT_IDS = "tango_object_ids";
65
66         /** Shared preference key to store the name of the account in use. */
67         @VisibleForTesting
68         public static final String SYNC_ACCT_NAME = "sync_acct_name";
69
70         /** Shared preference key to store the type of account in use. */
71         static final String SYNC_ACCT_TYPE = "sync_acct_type";
72
73         /** Shared preference key to store internal notification client library state. */
74         static final String SYNC_TANGO_INTERNAL_STATE = "sync_tango_internal_state";
75     }
76
77     private static final String TAG = "InvalidationPreferences";
78
79     private final Context mContext;
80
81     public InvalidationPreferences(Context context) {
82         this.mContext = Preconditions.checkNotNull(context.getApplicationContext());
83     }
84
85     /** Returns a new {@link EditContext} to modify the preferences managed by this class. */
86     public EditContext edit() {
87         return new EditContext();
88     }
89
90     /**
91      * Applies the changes accumulated in {@code editContext}. Returns whether they were
92      * successfully written.
93      * <p>
94      * NOTE: this method performs blocking I/O and must not be called from the UI thread.
95      */
96     public boolean commit(EditContext editContext) {
97         if (!editContext.mEditor.commit()) {
98             Log.w(TAG, "Failed to commit invalidation preferences");
99             return false;
100         }
101         return true;
102     }
103
104     /** Returns the saved sync types, or {@code null} if none exist. */
105     @Nullable public Set<String> getSavedSyncedTypes() {
106         SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
107         return preferences.getStringSet(PrefKeys.SYNC_TANGO_TYPES, null);
108     }
109
110     /** Sets the saved sync types to {@code syncTypes} in {@code editContext}. */
111     public void setSyncTypes(EditContext editContext, Collection<String> syncTypes) {
112         Preconditions.checkNotNull(syncTypes);
113         Set<String> selectedTypesSet = new HashSet<String>(syncTypes);
114         editContext.mEditor.putStringSet(PrefKeys.SYNC_TANGO_TYPES, selectedTypesSet);
115     }
116
117     /** Returns the saved non-sync object ids, or {@code null} if none exist. */
118     @Nullable
119     public Set<ObjectId> getSavedObjectIds() {
120         SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
121         Set<String> objectIdStrings = preferences.getStringSet(PrefKeys.TANGO_OBJECT_IDS, null);
122         if (objectIdStrings == null) {
123             return null;
124         }
125         Set<ObjectId> objectIds = new HashSet<ObjectId>(objectIdStrings.size());
126         for (String objectIdString : objectIdStrings) {
127             ObjectId objectId = getObjectId(objectIdString);
128             if (objectId != null) {
129                 objectIds.add(objectId);
130             }
131         }
132         return objectIds;
133     }
134
135     /** Sets the saved non-sync object ids */
136     public void setObjectIds(EditContext editContext, Collection<ObjectId> objectIds) {
137         Preconditions.checkNotNull(objectIds);
138         Set<String> objectIdStrings = new HashSet<String>(objectIds.size());
139         for (ObjectId objectId : objectIds) {
140             objectIdStrings.add(getObjectIdString(objectId));
141         }
142         editContext.mEditor.putStringSet(PrefKeys.TANGO_OBJECT_IDS, objectIdStrings);
143     }
144
145     /** Returns the saved account, or {@code null} if none exists. */
146     @Nullable public Account getSavedSyncedAccount() {
147         SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
148         String accountName = preferences.getString(PrefKeys.SYNC_ACCT_NAME, null);
149         String accountType = preferences.getString(PrefKeys.SYNC_ACCT_TYPE, null);
150         if (accountName == null || accountType == null) {
151             return null;
152         }
153         return new Account(accountName, accountType);
154     }
155
156     /** Sets the saved account to {@code account} in {@code editContext}. */
157     public void setAccount(EditContext editContext, Account account) {
158         editContext.mEditor.putString(PrefKeys.SYNC_ACCT_NAME, account.name);
159         editContext.mEditor.putString(PrefKeys.SYNC_ACCT_TYPE, account.type);
160     }
161
162     /** Returns the notification client internal state. */
163     @Nullable public byte[] getInternalNotificationClientState() {
164         SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
165         String base64State = preferences.getString(PrefKeys.SYNC_TANGO_INTERNAL_STATE, null);
166         if (base64State == null) {
167             return null;
168         }
169         return Base64.decode(base64State, Base64.DEFAULT);
170     }
171
172     /** Sets the notification client internal state to {@code state}. */
173     public void setInternalNotificationClientState(EditContext editContext, byte[] state) {
174         editContext.mEditor.putString(PrefKeys.SYNC_TANGO_INTERNAL_STATE,
175                 Base64.encodeToString(state, Base64.DEFAULT));
176     }
177
178     /** Converts the given object id to a string for storage in preferences. */
179     private String getObjectIdString(ObjectId objectId) {
180         return objectId.getSource() + ":" + new String(objectId.getName());
181     }
182
183     /**
184      * Converts the given object id string stored in preferences to an object id.
185      * Returns null if the string does not represent a valid object id.
186      */
187     private ObjectId getObjectId(String objectIdString) {
188         int separatorPos = objectIdString.indexOf(':');
189         // Ensure that the separator is surrounded by at least one character on each side.
190         if (separatorPos < 1 || separatorPos == objectIdString.length() - 1) {
191             return null;
192         }
193         int objectSource;
194         try {
195             objectSource = Integer.parseInt(objectIdString.substring(0, separatorPos));
196         } catch (NumberFormatException e) {
197             return null;
198         }
199         byte[] objectName = objectIdString.substring(separatorPos + 1).getBytes();
200         return ObjectId.newInstance(objectSource, objectName);
201     }
202 }