Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 package org.mozilla.gecko.db;
7 import java.io.IOException;
9 import org.json.JSONArray;
10 import org.json.JSONException;
11 import org.json.JSONObject;
12 import org.mozilla.gecko.R;
13 import org.mozilla.gecko.db.BrowserContract.HomeItems;
14 import org.mozilla.gecko.db.DBUtils;
15 import org.mozilla.gecko.sqlite.SQLiteBridge;
16 import org.mozilla.gecko.util.RawResource;
18 import android.content.ContentResolver;
19 import android.content.ContentValues;
20 import android.content.UriMatcher;
21 import android.database.Cursor;
22 import android.database.MatrixCursor;
23 import android.net.Uri;
24 import android.util.Log;
26 public class HomeProvider extends SQLiteBridgeContentProvider {
27 private static final String LOGTAG = "GeckoHomeProvider";
29 // This should be kept in sync with the db version in mobile/android/modules/HomeProvider.jsm
30 private static int DB_VERSION = 2;
31 private static String DB_FILENAME = "home.sqlite";
32 private static final String TELEMETRY_TAG = "SQLITEBRIDGE_PROVIDER_HOME";
34 private static final String TABLE_ITEMS = "items";
36 // Endpoint to return static fake data.
37 static final int ITEMS_FAKE = 100;
38 static final int ITEMS = 101;
39 static final int ITEMS_ID = 102;
41 static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
43 static {
44 URI_MATCHER.addURI(BrowserContract.HOME_AUTHORITY, "items/fake", ITEMS_FAKE);
45 URI_MATCHER.addURI(BrowserContract.HOME_AUTHORITY, "items", ITEMS);
46 URI_MATCHER.addURI(BrowserContract.HOME_AUTHORITY, "items/#", ITEMS_ID);
47 }
49 public HomeProvider() {
50 super(LOGTAG);
51 }
53 @Override
54 public String getType(Uri uri) {
55 final int match = URI_MATCHER.match(uri);
57 switch (match) {
58 case ITEMS_FAKE: {
59 return HomeItems.CONTENT_TYPE;
60 }
61 case ITEMS: {
62 return HomeItems.CONTENT_TYPE;
63 }
64 default: {
65 throw new UnsupportedOperationException("Unknown type " + uri);
66 }
67 }
68 }
70 @Override
71 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
72 final int match = URI_MATCHER.match(uri);
74 // If we're querying the fake items, don't try to get the database.
75 if (match == ITEMS_FAKE) {
76 return queryFakeItems(uri, projection, selection, selectionArgs, sortOrder);
77 }
79 final String datasetId = uri.getQueryParameter(BrowserContract.PARAM_DATASET_ID);
80 if (datasetId == null) {
81 throw new IllegalArgumentException("All queries should contain a dataset ID parameter");
82 }
84 selection = DBUtils.concatenateWhere(selection, HomeItems.DATASET_ID + " = ?");
85 selectionArgs = DBUtils.appendSelectionArgs(selectionArgs,
86 new String[] { datasetId });
88 // Otherwise, let the SQLiteContentProvider implementation take care of this query for us!
89 Cursor c = super.query(uri, projection, selection, selectionArgs, sortOrder);
91 // SQLiteBridgeContentProvider may return a null Cursor if the database hasn't been created yet.
92 // However, we need a non-null cursor in order to listen for notifications.
93 if (c == null) {
94 c = new MatrixCursor(projection != null ? projection : HomeItems.DEFAULT_PROJECTION);
95 }
97 final ContentResolver cr = getContext().getContentResolver();
98 c.setNotificationUri(cr, getDatasetNotificationUri(datasetId));
100 return c;
101 }
103 /**
104 * Returns a cursor populated with static fake data.
105 */
106 private Cursor queryFakeItems(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
107 JSONArray items = null;
108 try {
109 final String jsonString = RawResource.getAsString(getContext(), R.raw.fake_home_items);
110 items = new JSONArray(jsonString);
111 } catch (IOException e) {
112 Log.e(LOGTAG, "Error getting fake home items", e);
113 return null;
114 } catch (JSONException e) {
115 Log.e(LOGTAG, "Error parsing fake_home_items.json", e);
116 return null;
117 }
119 final MatrixCursor c = new MatrixCursor(HomeItems.DEFAULT_PROJECTION);
120 for (int i = 0; i < items.length(); i++) {
121 try {
122 final JSONObject item = items.getJSONObject(i);
123 c.addRow(new Object[] {
124 item.getInt("id"),
125 item.getString("dataset_id"),
126 item.getString("url"),
127 item.getString("title"),
128 item.getString("description"),
129 item.getString("image_url"),
130 item.getString("filter")
131 });
132 } catch (JSONException e) {
133 Log.e(LOGTAG, "Error creating cursor row for fake home item", e);
134 }
135 }
136 return c;
137 }
139 /**
140 * SQLiteBridgeContentProvider implementation
141 */
143 @Override
144 protected String getDBName(){
145 return DB_FILENAME;
146 }
148 @Override
149 protected String getTelemetryPrefix() {
150 return TELEMETRY_TAG;
151 }
153 @Override
154 protected int getDBVersion(){
155 return DB_VERSION;
156 }
158 @Override
159 public String getTable(Uri uri) {
160 final int match = URI_MATCHER.match(uri);
161 switch (match) {
162 case ITEMS: {
163 return TABLE_ITEMS;
164 }
165 default: {
166 throw new UnsupportedOperationException("Unknown table " + uri);
167 }
168 }
169 }
171 @Override
172 public String getSortOrder(Uri uri, String aRequested) {
173 return null;
174 }
176 @Override
177 public void setupDefaults(Uri uri, ContentValues values) { }
179 @Override
180 public void initGecko() { }
182 @Override
183 public void onPreInsert(ContentValues values, Uri uri, SQLiteBridge db) { }
185 @Override
186 public void onPreUpdate(ContentValues values, Uri uri, SQLiteBridge db) { }
188 @Override
189 public void onPostQuery(Cursor cursor, Uri uri, SQLiteBridge db) { }
191 public static Uri getDatasetNotificationUri(String datasetId) {
192 return Uri.withAppendedPath(HomeItems.CONTENT_URI, datasetId);
193 }
194 }