summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test/xpcshell/test_ext_schemas_privileged.js
blob: 496607968ec6c80eae9fa4e5b7ac59f21996845b (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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
"use strict";

const { ExtensionAPI } = ExtensionCommon;

AddonTestUtils.init(this);
AddonTestUtils.overrideCertDB();
AddonTestUtils.usePrivilegedSignatures = false;
AddonTestUtils.createAppInfo(
  "xpcshell@tests.mozilla.org",
  "XPCShell",
  "1",
  "42"
);

add_setup(async () => {
  const schema = [
    {
      namespace: "privileged",
      permissions: ["mozillaAddons"],
      properties: {
        test: {
          type: "any",
        },
      },
    },
  ];

  class API extends ExtensionAPI {
    getAPI() {
      return {
        privileged: {
          test: "hello",
        },
      };
    }
  }

  const modules = {
    privileged: {
      url: URL.createObjectURL(new Blob([API.toString()])),
      schema: `data:,${JSON.stringify(schema)}`,
      scopes: ["addon_parent"],
      paths: [["privileged"]],
    },
  };

  Services.catMan.addCategoryEntry(
    "webextension-modules",
    "test-privileged",
    `data:,${JSON.stringify(modules)}`,
    false,
    false
  );

  await AddonTestUtils.promiseStartupManager();

  registerCleanupFunction(async () => {
    await AddonTestUtils.promiseShutdownManager();
    Services.catMan.deleteCategoryEntry(
      "webextension-modules",
      "test-privileged",
      false
    );
  });
});

add_task(
  {
    // Some builds (e.g. thunderbird) have experiments enabled by default.
    pref_set: [["extensions.experiments.enabled", false]],
  },
  async function test_privileged_namespace_disallowed() {
    // Try accessing the privileged namespace.
    async function testOnce({
      isPrivileged = false,
      temporarilyInstalled = false,
    } = {}) {
      let extension = ExtensionTestUtils.loadExtension({
        manifest: {
          permissions: ["mozillaAddons", "tabs"],
        },
        background() {
          browser.test.sendMessage(
            "result",
            browser.privileged instanceof Object
          );
        },
        isPrivileged,
        temporarilyInstalled,
      });

      if (temporarilyInstalled && !isPrivileged) {
        ExtensionTestUtils.failOnSchemaWarnings(false);
        let { messages } = await promiseConsoleOutput(async () => {
          await Assert.rejects(
            extension.startup(),
            /Using the privileged permission/,
            "Startup failed with privileged permission"
          );
        });
        ExtensionTestUtils.failOnSchemaWarnings(true);
        AddonTestUtils.checkMessages(
          messages,
          {
            expected: [
              {
                message:
                  /Using the privileged permission 'mozillaAddons' requires a privileged add-on/,
              },
            ],
          },
          true
        );
        return null;
      }
      await extension.startup();
      let result = await extension.awaitMessage("result");
      await extension.unload();
      return result;
    }

    // Prevents startup
    let result = await testOnce({ temporarilyInstalled: true });
    equal(
      result,
      null,
      "Privileged namespace should not be accessible to a regular webextension"
    );

    result = await testOnce({ isPrivileged: true });
    equal(
      result,
      true,
      "Privileged namespace should be accessible to a webextension signed with Mozilla Extensions"
    );

    // Allows startup, no access
    result = await testOnce();
    equal(
      result,
      false,
      "Privileged namespace should not be accessible to a regular webextension"
    );
  }
);

// Test that Extension.sys.mjs and schema correctly match.
add_task(function test_privileged_permissions_match() {
  const { PRIVILEGED_PERMS } = ChromeUtils.importESModule(
    "resource://gre/modules/Extension.sys.mjs"
  );
  let perms = Schemas.getPermissionNames(["PermissionPrivileged"]);
  if (AppConstants.platform == "android") {
    perms.push("nativeMessaging");
  }
  Assert.deepEqual(
    Array.from(PRIVILEGED_PERMS).sort(),
    perms.sort(),
    "List of privileged permissions is correct."
  );
});