mobile/android/base/TabsAccessor.java

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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;
     7 import org.mozilla.gecko.db.BrowserContract;
     8 import org.mozilla.gecko.util.ThreadUtils;
     9 import org.mozilla.gecko.util.UiAsyncTask;
    11 import org.json.JSONArray;
    12 import org.json.JSONException;
    14 import android.content.ContentResolver;
    15 import android.content.ContentValues;
    16 import android.content.Context;
    17 import android.database.Cursor;
    18 import android.net.Uri;
    19 import android.util.Log;
    21 import java.util.ArrayList;
    22 import java.util.Collections;
    23 import java.util.List;
    25 public final class TabsAccessor {
    26     private static final String LOGTAG = "GeckoTabsAccessor";
    28     private static final String[] CLIENTS_AVAILABILITY_PROJECTION = new String[] {
    29                                                                         BrowserContract.Clients.GUID
    30                                                                     };
    32     private static final String[] TABS_PROJECTION_COLUMNS = new String[] {
    33                                                                 BrowserContract.Tabs.TITLE,
    34                                                                 BrowserContract.Tabs.URL,
    35                                                                 BrowserContract.Clients.GUID,
    36                                                                 BrowserContract.Clients.NAME
    37                                                             };
    39     // Projection column numbers
    40     public static enum TABS_COLUMN {
    41         TITLE,
    42         URL,
    43         GUID,
    44         NAME
    45     };
    47     private static final String CLIENTS_SELECTION = BrowserContract.Clients.GUID + " IS NOT NULL";
    48     private static final String TABS_SELECTION = BrowserContract.Tabs.CLIENT_GUID + " IS NOT NULL";
    50     private static final String LOCAL_CLIENT_SELECTION = BrowserContract.Clients.GUID + " IS NULL";
    51     private static final String LOCAL_TABS_SELECTION = BrowserContract.Tabs.CLIENT_GUID + " IS NULL";
    53     public static class RemoteTab {
    54         public String title;
    55         public String url;
    56         public String guid;
    57         public String name;
    58     }
    60     public interface OnQueryTabsCompleteListener {
    61         public void onQueryTabsComplete(List<RemoteTab> tabs);
    62     }
    64     // This method returns all tabs from all remote clients, 
    65     // ordered by most recent client first, most recent tab first 
    66     public static void getTabs(final Context context, final OnQueryTabsCompleteListener listener) {
    67         getTabs(context, 0, listener);
    68     }
    70     // This method returns limited number of tabs from all remote clients, 
    71     // ordered by most recent client first, most recent tab first 
    72     public static void getTabs(final Context context, final int limit, final OnQueryTabsCompleteListener listener) {
    73         // If there is no listener, no point in doing work.
    74         if (listener == null)
    75             return;
    77         (new UiAsyncTask<Void, Void, List<RemoteTab>>(ThreadUtils.getBackgroundHandler()) {
    78             @Override
    79             protected List<RemoteTab> doInBackground(Void... unused) {
    80                 Uri uri = BrowserContract.Tabs.CONTENT_URI;
    82                 if (limit > 0) {
    83                     uri = uri.buildUpon()
    84                              .appendQueryParameter(BrowserContract.PARAM_LIMIT, String.valueOf(limit))
    85                              .build();
    86                 }
    88                 Cursor cursor =  context.getContentResolver().query(uri,
    89                                                                     TABS_PROJECTION_COLUMNS,
    90                                                                     TABS_SELECTION,
    91                                                                     null,
    92                                                                     null);
    94                 if (cursor == null)
    95                     return null;
    97                 RemoteTab tab;
    98                 final ArrayList<RemoteTab> tabs = new ArrayList<RemoteTab> ();
    99                 try {
   100                     while (cursor.moveToNext()) {
   101                         tab = new RemoteTab();
   102                         tab.title = cursor.getString(TABS_COLUMN.TITLE.ordinal());
   103                         tab.url = cursor.getString(TABS_COLUMN.URL.ordinal());
   104                         tab.guid = cursor.getString(TABS_COLUMN.GUID.ordinal());
   105                         tab.name = cursor.getString(TABS_COLUMN.NAME.ordinal());
   107                         tabs.add(tab);
   108                     }
   109                 } finally {
   110                     cursor.close();
   111                 }
   113                 return Collections.unmodifiableList(tabs);
   114            }
   116             @Override
   117             protected void onPostExecute(List<RemoteTab> tabs) {
   118                 listener.onQueryTabsComplete(tabs);
   119             }
   120         }).execute();
   121     }
   123     // Updates the modified time of the local client with the current time.
   124     private static void updateLocalClient(final ContentResolver cr) {
   125         ContentValues values = new ContentValues();
   126         values.put(BrowserContract.Clients.LAST_MODIFIED, System.currentTimeMillis());
   127         cr.update(BrowserContract.Clients.CONTENT_URI, values, LOCAL_CLIENT_SELECTION, null);
   128     }
   130     // Deletes all local tabs.
   131     private static void deleteLocalTabs(final ContentResolver cr) {
   132         cr.delete(BrowserContract.Tabs.CONTENT_URI, LOCAL_TABS_SELECTION, null);
   133     }
   135     /**
   136      * Tabs are positioned in the DB in the same order that they appear in the tabs param.
   137      *   - URL should never empty or null. Skip this tab if there's no URL.
   138      *   - TITLE should always a string, either a page title or empty.
   139      *   - LAST_USED should always be numeric.
   140      *   - FAVICON should be a URL or null.
   141      *   - HISTORY should be serialized JSON array of URLs.
   142      *   - POSITION should always be numeric.
   143      *   - CLIENT_GUID should always be null to represent the local client.
   144      */
   145     private static void insertLocalTabs(final ContentResolver cr, final Iterable<Tab> tabs) {
   146         // Reuse this for serializing individual history URLs as JSON.
   147         JSONArray history = new JSONArray();
   148         ArrayList<ContentValues> valuesToInsert = new ArrayList<ContentValues>();
   150         int position = 0;
   151         for (Tab tab : tabs) {
   152             // Skip this tab if it has a null URL or is in private browsing mode
   153             String url = tab.getURL();
   154             if (url == null || tab.isPrivate())
   155                 continue;
   157             ContentValues values = new ContentValues();
   158             values.put(BrowserContract.Tabs.URL, url);
   159             values.put(BrowserContract.Tabs.TITLE, tab.getTitle());
   160             values.put(BrowserContract.Tabs.LAST_USED, tab.getLastUsed());
   162             String favicon = tab.getFaviconURL();
   163             if (favicon != null)
   164                 values.put(BrowserContract.Tabs.FAVICON, favicon);
   165             else
   166                 values.putNull(BrowserContract.Tabs.FAVICON);
   168             // We don't have access to session history in Java, so for now, we'll
   169             // just use a JSONArray that holds most recent history item.
   170             try {
   171                 history.put(0, tab.getURL());
   172                 values.put(BrowserContract.Tabs.HISTORY, history.toString());
   173             } catch (JSONException e) {
   174                 Log.w(LOGTAG, "JSONException adding URL to tab history array.", e);
   175             }
   177             values.put(BrowserContract.Tabs.POSITION, position++);
   179             // A null client guid corresponds to the local client.
   180             values.putNull(BrowserContract.Tabs.CLIENT_GUID);
   182             valuesToInsert.add(values);
   183         }
   185         ContentValues[] valuesToInsertArray = valuesToInsert.toArray(new ContentValues[valuesToInsert.size()]);
   186         cr.bulkInsert(BrowserContract.Tabs.CONTENT_URI, valuesToInsertArray);
   187     }
   189     // Deletes all local tabs and replaces them with a new list of tabs.
   190     public static synchronized void persistLocalTabs(final ContentResolver cr, final Iterable<Tab> tabs) {
   191         deleteLocalTabs(cr);
   192         insertLocalTabs(cr, tabs);
   193         updateLocalClient(cr);
   194     }
   195 }

mercurial