Bug 1833854 - Part 2: Common up GCSchedulingTunables invariant checks r=sfink
[gecko.git] / mobile / android / actors / GeckoViewPermissionChild.sys.mjs
blobf0224de2e9ed0c4690cc241ff4545511df154343
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 import { GeckoViewActorChild } from "resource://gre/modules/GeckoViewActorChild.sys.mjs";
7 const lazy = {};
9 ChromeUtils.defineESModuleGetters(lazy, {
10   E10SUtils: "resource://gre/modules/E10SUtils.sys.mjs",
11 });
13 const PERM_ACCESS_FINE_LOCATION = "android.permission.ACCESS_FINE_LOCATION";
15 export class GeckoViewPermissionChild extends GeckoViewActorChild {
16   getMediaPermission(aPermission) {
17     return this.eventDispatcher.sendRequestForResult({
18       type: "GeckoView:MediaPermission",
19       ...aPermission,
20     });
21   }
23   addCameraPermission() {
24     return this.sendQuery("AddCameraPermission");
25   }
27   getAppPermissions(aPermissions) {
28     return this.sendQuery("GetAppPermissions", aPermissions);
29   }
31   mediaRecordingStatusChanged(aDevices) {
32     return this.eventDispatcher.sendRequest({
33       type: "GeckoView:MediaRecordingStatusChanged",
34       devices: aDevices,
35     });
36   }
38   async promptPermission(aRequest) {
39     // Only allow exactly one permission request here.
40     const types = aRequest.types.QueryInterface(Ci.nsIArray);
41     if (types.length !== 1) {
42       return { allow: false };
43     }
45     const perm = types.queryElementAt(0, Ci.nsIContentPermissionType);
46     if (
47       perm.type === "desktop-notification" &&
48       !aRequest.hasValidTransientUserGestureActivation &&
49       Services.prefs.getBoolPref(
50         "dom.webnotifications.requireuserinteraction",
51         true
52       )
53     ) {
54       // We need user interaction and don't have it.
55       return { allow: false };
56     }
58     const principal =
59       perm.type === "storage-access"
60         ? aRequest.principal
61         : aRequest.topLevelPrincipal;
63     let allowOrDeny;
64     try {
65       allowOrDeny = await this.eventDispatcher.sendRequestForResult({
66         type: "GeckoView:ContentPermission",
67         uri: principal.URI.displaySpec,
68         thirdPartyOrigin: aRequest.principal.origin,
69         principal: lazy.E10SUtils.serializePrincipal(principal),
70         perm: perm.type,
71         value: perm.capability,
72         contextId: principal.originAttributes.geckoViewSessionContextId ?? null,
73         privateMode: principal.privateBrowsingId != 0,
74       });
76       if (allowOrDeny === Services.perms.ALLOW_ACTION) {
77         // Ask for app permission after asking for content permission.
78         if (perm.type === "geolocation") {
79           const granted = await this.getAppPermissions([
80             PERM_ACCESS_FINE_LOCATION,
81           ]);
82           allowOrDeny = granted
83             ? Services.perms.ALLOW_ACTION
84             : Services.perms.DENY_ACTION;
85         }
86       }
87     } catch (error) {
88       console.error("Permission error: " + error);
89       allowOrDeny = Services.perms.DENY_ACTION;
90     }
92     // Manually release the target request here to facilitate garbage collection.
93     aRequest = undefined;
95     const allow = allowOrDeny === Services.perms.ALLOW_ACTION;
97     // The storage access code adds itself to the perm manager; no need for us to do it.
98     if (perm.type === "storage-access") {
99       if (allow) {
100         return { allow, permission: { "storage-access": "allow" } };
101       }
102       return { allow };
103     }
105     Services.perms.addFromPrincipal(
106       principal,
107       perm.type,
108       allowOrDeny,
109       Services.perms.EXPIRE_NEVER
110     );
112     return { allow };
113   }
116 const { debug, warn } = GeckoViewPermissionChild.initLogging(
117   "GeckoViewPermissionChild"