aboutsummaryrefslogtreecommitdiffstats
path: root/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixList.kt
blob: eedde89f6af1be95aa7275410600e620896c4b53 (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
/*
 * SPDX-License-Identifier: (LGPL-3.0-only WITH LGPL-3.0-linking-exception) OR MPL-2.0
 */

/* 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 mozilla.components.lib.publicsuffixlist

import android.content.Context
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async

/**
 * API for reading and accessing the public suffix list.
 * > A "public suffix" is one under which Internet users can (or historically could) directly
 * > register names. Some > examples of public suffixes are .com, .co.uk and pvt.k12.ma.us. The
 * > Public Suffix List is a list of all known > public suffixes.
 *
 * Note that this implementation applies the rules of the public suffix list only and does not
 * validate domains.
 *
 * https://publicsuffix.org/ https://github.com/publicsuffix/list
 */
internal class PublicSuffixList(
  context: Context,
  dispatcher: CoroutineDispatcher = Dispatchers.IO,
  private val scope: CoroutineScope = CoroutineScope(dispatcher),
) {

  private val data: PublicSuffixListData by
    lazy(LazyThreadSafetyMode.PUBLICATION) { PublicSuffixListLoader.load(context) }

  /** Prefetch the public suffix list from disk so that it is available in memory. */
  fun prefetchAsync(): Deferred<Unit> = scope.async { data.run {} }

  /**
   * Returns the public suffix and one more level; known as the registrable domain. Returns `null`
   * if [domain] is a public suffix itself.
   *
   * E.g.:
   * ```
   * wwww.mozilla.org -> mozilla.org
   * www.bcc.co.uk    -> bbc.co.uk
   * a.b.ide.kyoto.jp -> b.ide.kyoto.jp
   * ```
   *
   * @param [domain] _must_ be a valid domain. [PublicSuffixList] performs no validation, and if any
   *   unexpected values are passed (e.g., a full URL, a domain with a trailing '/', etc) this may
   *   return an incorrect result.
   */
  fun getPublicSuffixPlusOneAsync(domain: String): Deferred<String?> =
    scope.async {
      when (val offset = data.getPublicSuffixOffset(domain)) {
        is PublicSuffixOffset.Offset ->
          domain.split('.').drop(offset.value).joinToString(separator = ".")
        else -> null
      }
    }
}