|
11 | 11 | import android.graphics.PointF;
|
12 | 12 | import android.graphics.Rect;
|
13 | 13 | import android.graphics.SurfaceTexture;
|
| 14 | +import android.net.Uri; |
14 | 15 | import android.util.Log;
|
15 | 16 | import android.util.Pair;
|
16 | 17 | import android.view.KeyEvent;
|
|
27 | 28 | import androidx.annotation.UiThread;
|
28 | 29 |
|
29 | 30 | import org.jetbrains.annotations.NotNull;
|
30 |
| -import org.mozilla.geckoview.AllowOrDeny; |
31 | 31 | import org.mozilla.geckoview.GeckoResult;
|
32 | 32 | import org.mozilla.geckoview.GeckoSession;
|
33 | 33 | import org.mozilla.geckoview.PanZoomController;
|
|
66 | 66 | import java.util.Arrays;
|
67 | 67 | import java.util.Calendar;
|
68 | 68 | import java.util.GregorianCalendar;
|
| 69 | +import java.util.List; |
69 | 70 | import java.util.concurrent.CopyOnWriteArrayList;
|
70 | 71 | import java.util.concurrent.Executor;
|
| 72 | +import java.util.stream.Collectors; |
| 73 | +import java.util.stream.Stream; |
71 | 74 |
|
72 | 75 | import mozilla.components.concept.storage.PageObservation;
|
73 | 76 | import mozilla.components.concept.storage.PageVisit;
|
@@ -1613,28 +1616,86 @@ public GeckoResult<Boolean> onVisited(@NonNull GeckoSession geckoSession, @NonNu
|
1613 | 1616 | return GeckoResult.fromValue(false);
|
1614 | 1617 | }
|
1615 | 1618 |
|
| 1619 | + // Check if we want this type of url. |
| 1620 | + if (!shouldStoreUri(url)) { |
| 1621 | + return GeckoResult.fromValue(false); |
| 1622 | + } |
| 1623 | + |
1616 | 1624 | boolean isReload = lastVisitedURL != null && lastVisitedURL.equals(url);
|
1617 | 1625 |
|
1618 |
| - PageVisit pageVisit; |
| 1626 | + VisitType visitType; |
1619 | 1627 | if (isReload) {
|
1620 |
| - pageVisit = new PageVisit(VisitType.RELOAD, RedirectSource.NOT_A_SOURCE); |
| 1628 | + visitType = VisitType.RELOAD; |
1621 | 1629 |
|
1622 | 1630 | } else {
|
1623 |
| - if ((flags & VISIT_REDIRECT_SOURCE_PERMANENT) != 0) { |
1624 |
| - pageVisit = new PageVisit(VisitType.REDIRECT_PERMANENT, RedirectSource.NOT_A_SOURCE); |
1625 |
| - } else if ((flags & VISIT_REDIRECT_SOURCE) != 0) { |
1626 |
| - pageVisit = new PageVisit(VisitType.REDIRECT_TEMPORARY, RedirectSource.NOT_A_SOURCE); |
| 1631 | + // Note the difference between `VISIT_REDIRECT_PERMANENT`, |
| 1632 | + // `VISIT_REDIRECT_TEMPORARY`, `VISIT_REDIRECT_SOURCE`, and |
| 1633 | + // `VISIT_REDIRECT_SOURCE_PERMANENT`. |
| 1634 | + // |
| 1635 | + // The former two indicate if the visited page is the *target* |
| 1636 | + // of a redirect; that is, another page redirected to it. |
| 1637 | + // |
| 1638 | + // The latter two indicate if the visited page is the *source* |
| 1639 | + // of a redirect: it's redirecting to another page, because the |
| 1640 | + // server returned an HTTP 3xy status code. |
| 1641 | + if ((flags & VISIT_REDIRECT_PERMANENT) != 0) { |
| 1642 | + visitType = VisitType.REDIRECT_PERMANENT; |
| 1643 | + |
| 1644 | + } else if ((flags & VISIT_REDIRECT_TEMPORARY) != 0) { |
| 1645 | + visitType = VisitType.REDIRECT_TEMPORARY; |
| 1646 | + |
1627 | 1647 | } else {
|
1628 |
| - pageVisit = new PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE); |
| 1648 | + visitType = VisitType.LINK; |
1629 | 1649 | }
|
1630 | 1650 | }
|
| 1651 | + RedirectSource redirectSource; |
| 1652 | + if ((flags & GeckoSession.HistoryDelegate.VISIT_REDIRECT_SOURCE_PERMANENT) != 0) { |
| 1653 | + redirectSource = RedirectSource.PERMANENT; |
| 1654 | + |
| 1655 | + } else if ((flags & GeckoSession.HistoryDelegate.VISIT_REDIRECT_SOURCE) != 0) { |
| 1656 | + redirectSource = RedirectSource.TEMPORARY; |
| 1657 | + |
| 1658 | + } else { |
| 1659 | + redirectSource = RedirectSource.NOT_A_SOURCE; |
| 1660 | + } |
1631 | 1661 |
|
1632 |
| - SessionStore.get().getHistoryStore().recordVisit(url, pageVisit); |
| 1662 | + SessionStore.get().getHistoryStore().recordVisit(url, new PageVisit(visitType, redirectSource)); |
1633 | 1663 | SessionStore.get().getHistoryStore().recordObservation(url, new PageObservation(url));
|
1634 | 1664 |
|
1635 | 1665 | return GeckoResult.fromValue(true);
|
1636 | 1666 | }
|
1637 | 1667 |
|
| 1668 | + /** |
| 1669 | + * Filter out unwanted URIs, such as "chrome:", "about:", etc. |
| 1670 | + * Ported from nsAndroidHistory::CanAddURI |
| 1671 | + * See https://dxr.mozilla.org/mozilla-central/source/mobile/android/components/build/nsAndroidHistory.cpp#326 |
| 1672 | + */ |
| 1673 | + private boolean shouldStoreUri(@NonNull String uri) { |
| 1674 | + Uri parsedUri = Uri.parse(uri); |
| 1675 | + String scheme = parsedUri.getScheme(); |
| 1676 | + if (scheme == null) { |
| 1677 | + return false; |
| 1678 | + } |
| 1679 | + |
| 1680 | + // Short-circuit most common schemes. |
| 1681 | + if (scheme.equals("http") || scheme.equals("https")) { |
| 1682 | + return true; |
| 1683 | + } |
| 1684 | + |
| 1685 | + // Allow about about:reader uris. They are of the form: |
| 1686 | + // about:reader?url=http://some.interesting.page/to/read.html |
| 1687 | + if (uri.startsWith("about:reader")) { |
| 1688 | + return true; |
| 1689 | + } |
| 1690 | + |
| 1691 | + List<String> schemasToIgnore = Stream.of( |
| 1692 | + "about", "imap", "news", "mailbox", "moz-anno", "moz-extension", |
| 1693 | + "view-source", "chrome", "resource", "data", "javascript", "blob" |
| 1694 | + ).collect(Collectors.toList()); |
| 1695 | + |
| 1696 | + return !schemasToIgnore.contains(scheme); |
| 1697 | + } |
| 1698 | + |
1638 | 1699 | @UiThread
|
1639 | 1700 | @Nullable
|
1640 | 1701 | public GeckoResult<boolean[]> getVisited(@NonNull GeckoSession geckoSession, @NonNull String[] urls) {
|
|
0 commit comments