mobile/android/base/GlobalHistory.java

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/mobile/android/base/GlobalHistory.java	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,123 @@
     1.4 +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
     1.5 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +package org.mozilla.gecko;
    1.10 +
    1.11 +import org.mozilla.gecko.db.BrowserDB;
    1.12 +import org.mozilla.gecko.util.ThreadUtils;
    1.13 +
    1.14 +import android.database.Cursor;
    1.15 +import android.net.Uri;
    1.16 +import android.os.Handler;
    1.17 +import android.util.Log;
    1.18 +
    1.19 +import java.lang.ref.SoftReference;
    1.20 +import java.util.HashSet;
    1.21 +import java.util.LinkedList;
    1.22 +import java.util.Queue;
    1.23 +import java.util.Set;
    1.24 +
    1.25 +class GlobalHistory {
    1.26 +    private static final String LOGTAG = "GeckoGlobalHistory";
    1.27 +
    1.28 +    private static GlobalHistory sInstance = new GlobalHistory();
    1.29 +
    1.30 +    static GlobalHistory getInstance() {
    1.31 +        return sInstance;
    1.32 +    }
    1.33 +
    1.34 +    // this is the delay between receiving a URI check request and processing it.
    1.35 +    // this allows batching together multiple requests and processing them together,
    1.36 +    // which is more efficient.
    1.37 +    private static final long BATCHING_DELAY_MS = 100;
    1.38 +
    1.39 +    private final Handler mHandler;                     // a background thread on which we can process requests
    1.40 +    private final Queue<String> mPendingUris;           // URIs that need to be checked
    1.41 +    private SoftReference<Set<String>> mVisitedCache;   // cache of the visited URI list
    1.42 +    private final Runnable mNotifierRunnable;           // off-thread runnable used to check URIs
    1.43 +    private boolean mProcessing; // = false             // whether or not the runnable is queued/working
    1.44 +
    1.45 +    private GlobalHistory() {
    1.46 +        mHandler = ThreadUtils.getBackgroundHandler();
    1.47 +        mPendingUris = new LinkedList<String>();
    1.48 +        mVisitedCache = new SoftReference<Set<String>>(null);
    1.49 +        mNotifierRunnable = new Runnable() {
    1.50 +            @Override
    1.51 +            public void run() {
    1.52 +                Set<String> visitedSet = mVisitedCache.get();
    1.53 +                if (visitedSet == null) {
    1.54 +                    // the cache was wiped away, repopulate it
    1.55 +                    Log.w(LOGTAG, "Rebuilding visited link set...");
    1.56 +                    visitedSet = new HashSet<String>();
    1.57 +                    Cursor c = null;
    1.58 +                    try {
    1.59 +                        c = BrowserDB.getAllVisitedHistory(GeckoAppShell.getContext().getContentResolver());
    1.60 +                        if (c == null) {
    1.61 +                            return;
    1.62 +                        }
    1.63 +
    1.64 +                        if (c.moveToFirst()) {
    1.65 +                            do {
    1.66 +                                visitedSet.add(c.getString(0));
    1.67 +                            } while (c.moveToNext());
    1.68 +                        }
    1.69 +                        mVisitedCache = new SoftReference<Set<String>>(visitedSet);
    1.70 +                    } finally {
    1.71 +                        if (c != null)
    1.72 +                            c.close();
    1.73 +                    }
    1.74 +                }
    1.75 +
    1.76 +                // this runs on the same handler thread as the checkUriVisited code,
    1.77 +                // so no synchronization needed
    1.78 +                while (true) {
    1.79 +                    String uri = mPendingUris.poll();
    1.80 +                    if (uri == null) {
    1.81 +                        break;
    1.82 +                    }
    1.83 +                    if (visitedSet.contains(uri)) {
    1.84 +                        GeckoAppShell.notifyUriVisited(uri);
    1.85 +                    }
    1.86 +                }
    1.87 +                mProcessing = false;
    1.88 +            }
    1.89 +        };
    1.90 +    }
    1.91 +
    1.92 +    public void addToGeckoOnly(String uri) {
    1.93 +        Set<String> visitedSet = mVisitedCache.get();
    1.94 +        if (visitedSet != null) {
    1.95 +            visitedSet.add(uri);
    1.96 +        }
    1.97 +        GeckoAppShell.notifyUriVisited(uri);
    1.98 +    }
    1.99 +
   1.100 +    public void add(String uri) {
   1.101 +        BrowserDB.updateVisitedHistory(GeckoAppShell.getContext().getContentResolver(), uri);
   1.102 +        addToGeckoOnly(uri);
   1.103 +    }
   1.104 +
   1.105 +    public void update(String uri, String title) {
   1.106 +        BrowserDB.updateHistoryTitle(GeckoAppShell.getContext().getContentResolver(), uri, title);
   1.107 +    }
   1.108 +
   1.109 +    public void checkUriVisited(final String uri) {
   1.110 +        mHandler.post(new Runnable() {
   1.111 +            @Override
   1.112 +            public void run() {
   1.113 +                // this runs on the same handler thread as the processing loop,
   1.114 +                // so no synchronization needed
   1.115 +                mPendingUris.add(uri);
   1.116 +                if (mProcessing) {
   1.117 +                    // there's already a runnable queued up or working away, so
   1.118 +                    // no need to post another
   1.119 +                    return;
   1.120 +                }
   1.121 +                mProcessing = true;
   1.122 +                mHandler.postDelayed(mNotifierRunnable, BATCHING_DELAY_MS);
   1.123 +            }
   1.124 +        });
   1.125 +    }
   1.126 +}

mercurial