summaryrefslogtreecommitdiffstats
path: root/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionFinder.java
blob: 2ed0b1a6c39cbf3d37aeb3c2a85be392cfaae459 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
 * 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.geckoview;

import android.util.Pair;
import androidx.annotation.AnyThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.Arrays;
import java.util.List;
import org.mozilla.gecko.EventDispatcher;
import org.mozilla.gecko.util.GeckoBundle;
import org.mozilla.geckoview.GeckoSession.FinderDisplayFlags;
import org.mozilla.geckoview.GeckoSession.FinderFindFlags;
import org.mozilla.geckoview.GeckoSession.FinderResult;

/**
 * {@code SessionFinder} instances returned by {@link GeckoSession#getFinder()} performs
 * find-in-page operations.
 */
@AnyThread
public final class SessionFinder {
  private static final String LOGTAG = "GeckoSessionFinder";

  private static final List<Pair<Integer, String>> sFlagNames =
      Arrays.asList(
          new Pair<>(GeckoSession.FINDER_FIND_BACKWARDS, "backwards"),
          new Pair<>(GeckoSession.FINDER_FIND_LINKS_ONLY, "linksOnly"),
          new Pair<>(GeckoSession.FINDER_FIND_MATCH_CASE, "matchCase"),
          new Pair<>(GeckoSession.FINDER_FIND_WHOLE_WORD, "wholeWord"));

  private static void addFlagsToBundle(
      @FinderFindFlags final int flags, @NonNull final GeckoBundle bundle) {
    for (final Pair<Integer, String> name : sFlagNames) {
      if ((flags & name.first) != 0) {
        bundle.putBoolean(name.second, true);
      }
    }
  }

  /* package */ static int getFlagsFromBundle(@Nullable final GeckoBundle bundle) {
    if (bundle == null) {
      return 0;
    }

    int flags = 0;
    for (final Pair<Integer, String> name : sFlagNames) {
      if (bundle.getBoolean(name.second)) {
        flags |= name.first;
      }
    }
    return flags;
  }

  private final EventDispatcher mDispatcher;
  @FinderDisplayFlags private int mDisplayFlags;

  /* package */ SessionFinder(@NonNull final EventDispatcher dispatcher) {
    mDispatcher = dispatcher;
    setDisplayFlags(0);
  }

  /**
   * Find and select a string on the current page, starting from the current selection or the start
   * of the page if there is no selection. Optionally return results related to the search in a
   * {@link FinderResult} object. If {@code searchString} is null, search is performed using the
   * previous search string.
   *
   * @param searchString String to search, or null to find again using the previous string.
   * @param flags Flags for performing the search; either 0 or a combination of {@link
   *     GeckoSession#FINDER_FIND_BACKWARDS FINDER_FIND_*} constants.
   * @return Result of the search operation as a {@link GeckoResult} object.
   * @see #clear
   * @see #setDisplayFlags
   */
  @NonNull
  public GeckoResult<FinderResult> find(
      @Nullable final String searchString, @FinderFindFlags final int flags) {
    final GeckoBundle bundle = new GeckoBundle(sFlagNames.size() + 1);
    bundle.putString("searchString", searchString);
    addFlagsToBundle(flags, bundle);

    return mDispatcher
        .queryBundle("GeckoView:FindInPage", bundle)
        .map(response -> new FinderResult(response));
  }

  /**
   * Clear any highlighted find-in-page matches.
   *
   * @see #find
   * @see #setDisplayFlags
   */
  public void clear() {
    mDispatcher.dispatch("GeckoView:ClearMatches", null);
  }

  /**
   * Return flags for displaying find-in-page matches.
   *
   * @return Display flags as a combination of {@link GeckoSession#FINDER_DISPLAY_HIGHLIGHT_ALL
   *     FINDER_DISPLAY_*} constants.
   * @see #setDisplayFlags
   * @see #find
   */
  @FinderDisplayFlags
  public int getDisplayFlags() {
    return mDisplayFlags;
  }

  /**
   * Set flags for displaying find-in-page matches.
   *
   * @param flags Display flags as a combination of {@link GeckoSession#FINDER_DISPLAY_HIGHLIGHT_ALL
   *     FINDER_DISPLAY_*} constants.
   * @see #getDisplayFlags
   * @see #find
   */
  public void setDisplayFlags(@FinderDisplayFlags final int flags) {
    mDisplayFlags = flags;

    final GeckoBundle bundle = new GeckoBundle(3);
    bundle.putBoolean("highlightAll", (flags & GeckoSession.FINDER_DISPLAY_HIGHLIGHT_ALL) != 0);
    bundle.putBoolean("dimPage", (flags & GeckoSession.FINDER_DISPLAY_DIM_PAGE) != 0);
    bundle.putBoolean("drawOutline", (flags & GeckoSession.FINDER_DISPLAY_DRAW_LINK_OUTLINE) != 0);
    mDispatcher.dispatch("GeckoView:DisplayMatches", bundle);
  }
}