summaryrefslogtreecommitdiffstats
path: root/mobile/android/modules/geckoview/LoadURIDelegate.sys.mjs
blob: fa65b8a2e2e523490cbd8f3223aed03c5c486d21 (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
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
/* 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/. */

import { GeckoViewUtils } from "resource://gre/modules/GeckoViewUtils.sys.mjs";

const { debug, warn } = GeckoViewUtils.initLogging("LoadURIDelegate");

export const LoadURIDelegate = {
  // Delegate URI loading to the app.
  // Return whether the loading has been handled.
  load(aWindow, aEventDispatcher, aUri, aWhere, aFlags, aTriggeringPrincipal) {
    if (!aWindow) {
      return false;
    }

    const triggerUri =
      aTriggeringPrincipal &&
      (aTriggeringPrincipal.isNullPrincipal ? null : aTriggeringPrincipal.URI);

    const message = {
      type: "GeckoView:OnLoadRequest",
      uri: aUri ? aUri.displaySpec : "",
      where: aWhere,
      flags: aFlags,
      triggerUri: triggerUri && triggerUri.displaySpec,
      hasUserGesture: aWindow.document.hasValidTransientUserGestureActivation,
    };

    let handled = undefined;
    aEventDispatcher.sendRequestForResult(message).then(
      response => {
        handled = response;
      },
      () => {
        // There was an error or listener was not registered in GeckoSession,
        // treat as unhandled.
        handled = false;
      }
    );
    Services.tm.spinEventLoopUntil(
      "LoadURIDelegate.sys.mjs:load",
      () => aWindow.closed || handled !== undefined
    );

    return handled || false;
  },

  handleLoadError(aWindow, aEventDispatcher, aUri, aError, aErrorModule) {
    let errorClass = 0;
    try {
      const nssErrorsService = Cc[
        "@mozilla.org/nss_errors_service;1"
      ].getService(Ci.nsINSSErrorsService);
      errorClass = nssErrorsService.getErrorClass(aError);
    } catch (e) {}

    const msg = {
      type: "GeckoView:OnLoadError",
      uri: aUri && aUri.spec,
      error: aError,
      errorModule: aErrorModule,
      errorClass,
    };

    let errorPageURI = undefined;
    aEventDispatcher.sendRequestForResult(msg).then(
      response => {
        try {
          errorPageURI = response ? Services.io.newURI(response) : null;
        } catch (e) {
          warn`Failed to parse URI '${response}`;
          errorPageURI = null;
          Components.returnCode = Cr.NS_ERROR_ABORT;
        }
      },
      () => {
        errorPageURI = null;
        Components.returnCode = Cr.NS_ERROR_ABORT;
      }
    );
    Services.tm.spinEventLoopUntil(
      "LoadURIDelegate.sys.mjs:handleLoadError",
      () => aWindow.closed || errorPageURI !== undefined
    );

    return errorPageURI;
  },

  isSafeBrowsingError(aError) {
    return (
      aError === Cr.NS_ERROR_PHISHING_URI ||
      aError === Cr.NS_ERROR_MALWARE_URI ||
      aError === Cr.NS_ERROR_HARMFUL_URI ||
      aError === Cr.NS_ERROR_UNWANTED_URI
    );
  },
};