diff options
Diffstat (limited to 'mobile/android/base/java/org/mozilla/gecko/db/LocalTabsAccessor.java')
-rw-r--r-- | mobile/android/base/java/org/mozilla/gecko/db/LocalTabsAccessor.java | 320 |
1 files changed, 0 insertions, 320 deletions
diff --git a/mobile/android/base/java/org/mozilla/gecko/db/LocalTabsAccessor.java b/mobile/android/base/java/org/mozilla/gecko/db/LocalTabsAccessor.java deleted file mode 100644 index c7bd9475c..000000000 --- a/mobile/android/base/java/org/mozilla/gecko/db/LocalTabsAccessor.java +++ /dev/null @@ -1,320 +0,0 @@ -/* 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/. */ - -package org.mozilla.gecko.db; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.regex.Pattern; - -import org.json.JSONArray; -import org.json.JSONException; -import org.mozilla.gecko.Tab; -import org.mozilla.gecko.util.ThreadUtils; -import org.mozilla.gecko.util.UIAsyncTask; - -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.net.Uri; -import android.text.TextUtils; -import android.util.Log; - -public class LocalTabsAccessor implements TabsAccessor { - private static final String LOGTAG = "GeckoTabsAccessor"; - private static final long THREE_WEEKS_IN_MILLISECONDS = TimeUnit.MILLISECONDS.convert(21L, TimeUnit.DAYS); - - public static final String[] TABS_PROJECTION_COLUMNS = new String[] { - BrowserContract.Tabs.TITLE, - BrowserContract.Tabs.URL, - BrowserContract.Clients.GUID, - BrowserContract.Clients.NAME, - BrowserContract.Tabs.LAST_USED, - BrowserContract.Clients.LAST_MODIFIED, - BrowserContract.Clients.DEVICE_TYPE, - }; - - public static final String[] CLIENTS_PROJECTION_COLUMNS = new String[] { - BrowserContract.Clients.GUID, - BrowserContract.Clients.NAME, - BrowserContract.Clients.LAST_MODIFIED, - BrowserContract.Clients.DEVICE_TYPE - }; - - private static final String REMOTE_CLIENTS_SELECTION = BrowserContract.Clients.GUID + " IS NOT NULL"; - private static final String LOCAL_TABS_SELECTION = BrowserContract.Tabs.CLIENT_GUID + " IS NULL"; - private static final String REMOTE_TABS_SELECTION = BrowserContract.Tabs.CLIENT_GUID + " IS NOT NULL"; - private static final String REMOTE_TABS_SELECTION_CLIENT_RECENCY = REMOTE_TABS_SELECTION + - " AND " + BrowserContract.Clients.LAST_MODIFIED + " > ?"; - - private static final String REMOTE_TABS_SORT_ORDER = - // Most recently synced clients first. - BrowserContract.Clients.LAST_MODIFIED + " DESC, " + - // If two clients somehow had the same last modified time, this will - // group them (arbitrarily). - BrowserContract.Clients.GUID + " DESC, " + - // Within a single client, most recently used tabs first. - BrowserContract.Tabs.LAST_USED + " DESC"; - - private static final String LOCAL_CLIENT_SELECTION = BrowserContract.Clients.GUID + " IS NULL"; - - private static final Pattern FILTERED_URL_PATTERN = Pattern.compile("^(about|chrome|wyciwyg|file):"); - - private final Uri clientsRecencyUriWithProfile; - private final Uri tabsUriWithProfile; - private final Uri clientsUriWithProfile; - - public LocalTabsAccessor(String profileName) { - tabsUriWithProfile = DBUtils.appendProfileWithDefault(profileName, BrowserContract.Tabs.CONTENT_URI); - clientsUriWithProfile = DBUtils.appendProfileWithDefault(profileName, BrowserContract.Clients.CONTENT_URI); - clientsRecencyUriWithProfile = DBUtils.appendProfileWithDefault(profileName, BrowserContract.Clients.CONTENT_RECENCY_URI); - } - - /** - * Extracts a List of just RemoteClients from a cursor. - * The supplied cursor should be grouped by guid and sorted by most recently used. - */ - @Override - public List<RemoteClient> getClientsWithoutTabsByRecencyFromCursor(Cursor cursor) { - final ArrayList<RemoteClient> clients = new ArrayList<>(cursor.getCount()); - - final int originalPosition = cursor.getPosition(); - try { - if (!cursor.moveToFirst()) { - return clients; - } - - final int clientGuidIndex = cursor.getColumnIndex(BrowserContract.Clients.GUID); - final int clientNameIndex = cursor.getColumnIndex(BrowserContract.Clients.NAME); - final int clientLastModifiedIndex = cursor.getColumnIndex(BrowserContract.Clients.LAST_MODIFIED); - final int clientDeviceTypeIndex = cursor.getColumnIndex(BrowserContract.Clients.DEVICE_TYPE); - - while (!cursor.isAfterLast()) { - final String clientGuid = cursor.getString(clientGuidIndex); - final String clientName = cursor.getString(clientNameIndex); - final String deviceType = cursor.getString(clientDeviceTypeIndex); - final long lastModified = cursor.getLong(clientLastModifiedIndex); - - clients.add(new RemoteClient(clientGuid, clientName, lastModified, deviceType)); - - cursor.moveToNext(); - } - } finally { - cursor.moveToPosition(originalPosition); - } - return clients; - } - - /** - * Extract client and tab records from a cursor. - * <p> - * The position of the cursor is moved to before the first record before - * reading. The cursor is advanced until there are no more records to be - * read. The position of the cursor is restored before returning. - * - * @param cursor - * to extract records from. The records should already be grouped - * by client GUID. - * @return list of clients, each containing list of tabs. - */ - @Override - public List<RemoteClient> getClientsFromCursor(final Cursor cursor) { - final ArrayList<RemoteClient> clients = new ArrayList<RemoteClient>(); - - final int originalPosition = cursor.getPosition(); - try { - if (!cursor.moveToFirst()) { - return clients; - } - - final int tabTitleIndex = cursor.getColumnIndex(BrowserContract.Tabs.TITLE); - final int tabUrlIndex = cursor.getColumnIndex(BrowserContract.Tabs.URL); - final int tabLastUsedIndex = cursor.getColumnIndex(BrowserContract.Tabs.LAST_USED); - final int clientGuidIndex = cursor.getColumnIndex(BrowserContract.Clients.GUID); - final int clientNameIndex = cursor.getColumnIndex(BrowserContract.Clients.NAME); - final int clientLastModifiedIndex = cursor.getColumnIndex(BrowserContract.Clients.LAST_MODIFIED); - final int clientDeviceTypeIndex = cursor.getColumnIndex(BrowserContract.Clients.DEVICE_TYPE); - - // A walking partition, chunking by client GUID. We assume the - // cursor records are already grouped by client GUID; see the query - // sort order. - RemoteClient lastClient = null; - while (!cursor.isAfterLast()) { - final String clientGuid = cursor.getString(clientGuidIndex); - if (lastClient == null || !TextUtils.equals(lastClient.guid, clientGuid)) { - final String clientName = cursor.getString(clientNameIndex); - final long lastModified = cursor.getLong(clientLastModifiedIndex); - final String deviceType = cursor.getString(clientDeviceTypeIndex); - lastClient = new RemoteClient(clientGuid, clientName, lastModified, deviceType); - clients.add(lastClient); - } - - final String tabTitle = cursor.getString(tabTitleIndex); - final String tabUrl = cursor.getString(tabUrlIndex); - final long tabLastUsed = cursor.getLong(tabLastUsedIndex); - lastClient.tabs.add(new RemoteTab(tabTitle, tabUrl, tabLastUsed)); - - cursor.moveToNext(); - } - } finally { - cursor.moveToPosition(originalPosition); - } - - return clients; - } - - @Override - public Cursor getRemoteClientsByRecencyCursor(Context context) { - final Uri uri = clientsRecencyUriWithProfile; - return context.getContentResolver().query(uri, CLIENTS_PROJECTION_COLUMNS, - REMOTE_CLIENTS_SELECTION, null, null); - } - - @Override - public Cursor getRemoteTabsCursor(Context context) { - return getRemoteTabsCursor(context, -1); - } - - @Override - public Cursor getRemoteTabsCursor(Context context, int limit) { - Uri uri = tabsUriWithProfile; - - if (limit > 0) { - uri = uri.buildUpon() - .appendQueryParameter(BrowserContract.PARAM_LIMIT, String.valueOf(limit)) - .build(); - } - - final String threeWeeksAgoTimestampMillis = Long.valueOf( - System.currentTimeMillis() - THREE_WEEKS_IN_MILLISECONDS).toString(); - return context.getContentResolver().query(uri, - TABS_PROJECTION_COLUMNS, - REMOTE_TABS_SELECTION_CLIENT_RECENCY, - new String[] {threeWeeksAgoTimestampMillis}, - REMOTE_TABS_SORT_ORDER); - } - - // This method returns all tabs from all remote clients, - // ordered by most recent client first, most recent tab first - @Override - public void getTabs(final Context context, final OnQueryTabsCompleteListener listener) { - getTabs(context, 0, listener); - } - - // This method returns limited number of tabs from all remote clients, - // ordered by most recent client first, most recent tab first - @Override - public void getTabs(final Context context, final int limit, final OnQueryTabsCompleteListener listener) { - // If there is no listener, no point in doing work. - if (listener == null) - return; - - (new UIAsyncTask.WithoutParams<List<RemoteClient>>(ThreadUtils.getBackgroundHandler()) { - @Override - protected List<RemoteClient> doInBackground() { - final Cursor cursor = getRemoteTabsCursor(context, limit); - if (cursor == null) - return null; - - try { - return Collections.unmodifiableList(getClientsFromCursor(cursor)); - } finally { - cursor.close(); - } - } - - @Override - protected void onPostExecute(List<RemoteClient> clients) { - listener.onQueryTabsComplete(clients); - } - }).execute(); - } - - // Updates the modified time of the local client with the current time. - private void updateLocalClient(final ContentResolver cr) { - ContentValues values = new ContentValues(); - values.put(BrowserContract.Clients.LAST_MODIFIED, System.currentTimeMillis()); - - cr.update(clientsUriWithProfile, values, LOCAL_CLIENT_SELECTION, null); - } - - // Deletes all local tabs. - private void deleteLocalTabs(final ContentResolver cr) { - cr.delete(tabsUriWithProfile, LOCAL_TABS_SELECTION, null); - } - - /** - * Tabs are positioned in the DB in the same order that they appear in the tabs param. - * - URL should never empty or null. Skip this tab if there's no URL. - * - TITLE should always a string, either a page title or empty. - * - LAST_USED should always be numeric. - * - FAVICON should be a URL or null. - * - HISTORY should be serialized JSON array of URLs. - * - POSITION should always be numeric. - * - CLIENT_GUID should always be null to represent the local client. - */ - private void insertLocalTabs(final ContentResolver cr, final Iterable<Tab> tabs) { - // Reuse this for serializing individual history URLs as JSON. - JSONArray history = new JSONArray(); - ArrayList<ContentValues> valuesToInsert = new ArrayList<ContentValues>(); - - int position = 0; - for (Tab tab : tabs) { - // Skip this tab if it has a null URL or is in private browsing mode, or is a filtered URL. - String url = tab.getURL(); - if (url == null || tab.isPrivate() || isFilteredURL(url)) - continue; - - ContentValues values = new ContentValues(); - values.put(BrowserContract.Tabs.URL, url); - values.put(BrowserContract.Tabs.TITLE, tab.getTitle()); - values.put(BrowserContract.Tabs.LAST_USED, tab.getLastUsed()); - - String favicon = tab.getFaviconURL(); - if (favicon != null) - values.put(BrowserContract.Tabs.FAVICON, favicon); - else - values.putNull(BrowserContract.Tabs.FAVICON); - - // We don't have access to session history in Java, so for now, we'll - // just use a JSONArray that holds most recent history item. - try { - history.put(0, tab.getURL()); - values.put(BrowserContract.Tabs.HISTORY, history.toString()); - } catch (JSONException e) { - Log.w(LOGTAG, "JSONException adding URL to tab history array.", e); - } - - values.put(BrowserContract.Tabs.POSITION, position++); - - // A null client guid corresponds to the local client. - values.putNull(BrowserContract.Tabs.CLIENT_GUID); - - valuesToInsert.add(values); - } - - ContentValues[] valuesToInsertArray = valuesToInsert.toArray(new ContentValues[valuesToInsert.size()]); - cr.bulkInsert(tabsUriWithProfile, valuesToInsertArray); - } - - // Deletes all local tabs and replaces them with a new list of tabs. - @Override - public synchronized void persistLocalTabs(final ContentResolver cr, final Iterable<Tab> tabs) { - deleteLocalTabs(cr); - insertLocalTabs(cr, tabs); - updateLocalClient(cr); - } - - /** - * Matches the supplied URL string against the set of URLs to filter. - * - * @return true if the supplied URL should be skipped; false otherwise. - */ - private boolean isFilteredURL(String url) { - return FILTERED_URL_PATTERN.matcher(url).lookingAt(); - } -} |