mobile/android/base/GlobalHistory.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
     2  * This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 package org.mozilla.gecko;
     8 import org.mozilla.gecko.db.BrowserDB;
     9 import org.mozilla.gecko.util.ThreadUtils;
    11 import android.database.Cursor;
    12 import android.net.Uri;
    13 import android.os.Handler;
    14 import android.util.Log;
    16 import java.lang.ref.SoftReference;
    17 import java.util.HashSet;
    18 import java.util.LinkedList;
    19 import java.util.Queue;
    20 import java.util.Set;
    22 class GlobalHistory {
    23     private static final String LOGTAG = "GeckoGlobalHistory";
    25     private static GlobalHistory sInstance = new GlobalHistory();
    27     static GlobalHistory getInstance() {
    28         return sInstance;
    29     }
    31     // this is the delay between receiving a URI check request and processing it.
    32     // this allows batching together multiple requests and processing them together,
    33     // which is more efficient.
    34     private static final long BATCHING_DELAY_MS = 100;
    36     private final Handler mHandler;                     // a background thread on which we can process requests
    37     private final Queue<String> mPendingUris;           // URIs that need to be checked
    38     private SoftReference<Set<String>> mVisitedCache;   // cache of the visited URI list
    39     private final Runnable mNotifierRunnable;           // off-thread runnable used to check URIs
    40     private boolean mProcessing; // = false             // whether or not the runnable is queued/working
    42     private GlobalHistory() {
    43         mHandler = ThreadUtils.getBackgroundHandler();
    44         mPendingUris = new LinkedList<String>();
    45         mVisitedCache = new SoftReference<Set<String>>(null);
    46         mNotifierRunnable = new Runnable() {
    47             @Override
    48             public void run() {
    49                 Set<String> visitedSet = mVisitedCache.get();
    50                 if (visitedSet == null) {
    51                     // the cache was wiped away, repopulate it
    52                     Log.w(LOGTAG, "Rebuilding visited link set...");
    53                     visitedSet = new HashSet<String>();
    54                     Cursor c = null;
    55                     try {
    56                         c = BrowserDB.getAllVisitedHistory(GeckoAppShell.getContext().getContentResolver());
    57                         if (c == null) {
    58                             return;
    59                         }
    61                         if (c.moveToFirst()) {
    62                             do {
    63                                 visitedSet.add(c.getString(0));
    64                             } while (c.moveToNext());
    65                         }
    66                         mVisitedCache = new SoftReference<Set<String>>(visitedSet);
    67                     } finally {
    68                         if (c != null)
    69                             c.close();
    70                     }
    71                 }
    73                 // this runs on the same handler thread as the checkUriVisited code,
    74                 // so no synchronization needed
    75                 while (true) {
    76                     String uri = mPendingUris.poll();
    77                     if (uri == null) {
    78                         break;
    79                     }
    80                     if (visitedSet.contains(uri)) {
    81                         GeckoAppShell.notifyUriVisited(uri);
    82                     }
    83                 }
    84                 mProcessing = false;
    85             }
    86         };
    87     }
    89     public void addToGeckoOnly(String uri) {
    90         Set<String> visitedSet = mVisitedCache.get();
    91         if (visitedSet != null) {
    92             visitedSet.add(uri);
    93         }
    94         GeckoAppShell.notifyUriVisited(uri);
    95     }
    97     public void add(String uri) {
    98         BrowserDB.updateVisitedHistory(GeckoAppShell.getContext().getContentResolver(), uri);
    99         addToGeckoOnly(uri);
   100     }
   102     public void update(String uri, String title) {
   103         BrowserDB.updateHistoryTitle(GeckoAppShell.getContext().getContentResolver(), uri, title);
   104     }
   106     public void checkUriVisited(final String uri) {
   107         mHandler.post(new Runnable() {
   108             @Override
   109             public void run() {
   110                 // this runs on the same handler thread as the processing loop,
   111                 // so no synchronization needed
   112                 mPendingUris.add(uri);
   113                 if (mProcessing) {
   114                     // there's already a runnable queued up or working away, so
   115                     // no need to post another
   116                     return;
   117                 }
   118                 mProcessing = true;
   119                 mHandler.postDelayed(mNotifierRunnable, BATCHING_DELAY_MS);
   120             }
   121         });
   122     }
   123 }

mercurial