summaryrefslogtreecommitdiffstats
path: root/toolkit/components/passwordmgr/test/browser/browser_context_menu_iframe.js
blob: f997cf3a72678258f0031e53f437ec806b8cdbf6 (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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/*
 * Test the password manager context menu.
 */

"use strict";

const TEST_ORIGIN = "https://example.com";

// Test with a page that only has a form within an iframe, not in the top-level document
const IFRAME_PAGE_PATH =
  "/browser/toolkit/components/passwordmgr/test/browser/form_basic_iframe.html";

/**
 * Initialize logins needed for the tests and disable autofill
 * for login forms for easier testing of manual fill.
 */
add_task(async function test_initialize() {
  Services.prefs.setBoolPref("signon.autofillForms", false);
  Services.prefs.setBoolPref("signon.schemeUpgrades", true);
  registerCleanupFunction(() => {
    Services.prefs.clearUserPref("signon.autofillForms");
    Services.prefs.clearUserPref("signon.schemeUpgrades");
  });
  await Services.logins.addLogins(loginList());
});

/**
 * Check if the password field is correctly filled when it's in an iframe.
 */
add_task(async function test_context_menu_iframe_fill() {
  await BrowserTestUtils.withNewTab(
    {
      gBrowser,
      url: TEST_ORIGIN + IFRAME_PAGE_PATH,
    },
    async function (browser) {
      await openPasswordContextMenu(
        browser,
        "#form-basic-password",
        () => true,
        browser.browsingContext.children[0],
        true
      );

      let popupMenu = document.getElementById("fill-login-popup");

      // Stores the original value of username
      function promiseFrameInputValue(name) {
        return SpecialPowers.spawn(
          browser.browsingContext.children[0],
          [name],
          function (inputname) {
            return content.document.getElementById(inputname).value;
          }
        );
      }
      let usernameOriginalValue = await promiseFrameInputValue(
        "form-basic-username"
      );

      // Execute the command of the first login menuitem found at the context menu.
      let firstLoginItem =
        popupMenu.getElementsByClassName("context-login-item")[0];
      Assert.ok(firstLoginItem, "Found the first login item");

      await TestUtils.waitForTick();

      Assert.ok(
        BrowserTestUtils.isVisible(firstLoginItem),
        "First login menuitem is visible"
      );

      info("Clicking on the firstLoginItem");
      // click on the login item to fill the password field, triggering an "input" event
      popupMenu.activateItem(firstLoginItem);

      let passwordValue = await TestUtils.waitForCondition(async () => {
        let value = await promiseFrameInputValue("form-basic-password");
        return value;
      });

      // Find the used login by it's username.
      let login = getLoginFromUsername(firstLoginItem.label);
      Assert.equal(
        login.password,
        passwordValue,
        "Password filled and correct."
      );

      let usernameNewValue = await promiseFrameInputValue(
        "form-basic-username"
      );
      Assert.equal(
        usernameOriginalValue,
        usernameNewValue,
        "Username value was not changed."
      );

      let contextMenu = document.getElementById("contentAreaContextMenu");
      contextMenu.hidePopup();

      await cleanupDoorhanger();
      await cleanupPasswordNotifications();
    }
  );
});

/**
 * Check that the login context menu items don't appear on an opaque origin.
 */
add_task(async function test_context_menu_iframe_sandbox() {
  await BrowserTestUtils.withNewTab(
    {
      gBrowser,
      url: TEST_ORIGIN + IFRAME_PAGE_PATH,
    },
    async function (browser) {
      info("Opening context menu for test_context_menu_iframe_sandbox");
      await openPasswordContextMenu(
        browser,
        "#form-basic-password",
        function checkDisabled() {
          info("checkDisabled for test_context_menu_iframe_sandbox");
          let popupHeader = document.getElementById("fill-login");
          Assert.ok(
            popupHeader.hidden,
            "Check that the Fill Login menu item is hidden"
          );
          return false;
        },
        browser.browsingContext.children[1]
      );
      let contextMenu = document.getElementById("contentAreaContextMenu");
      contextMenu.hidePopup();
    }
  );
});

/**
 * Check that the login context menu item appears for sandbox="allow-same-origin"
 */
add_task(async function test_context_menu_iframe_sandbox_same_origin() {
  await BrowserTestUtils.withNewTab(
    {
      gBrowser,
      url: TEST_ORIGIN + IFRAME_PAGE_PATH,
    },
    async function (browser) {
      await openPasswordContextMenu(
        browser,
        "#form-basic-password",
        function checkDisabled() {
          let popupHeader = document.getElementById("fill-login");
          Assert.ok(
            !popupHeader.hidden,
            "Check that the Fill Login menu item is visible"
          );
          Assert.ok(
            !popupHeader.disabled,
            "Check that the Fill Login menu item is disabled"
          );
          return false;
        },
        browser.browsingContext.children[2]
      );

      let contextMenu = document.getElementById("contentAreaContextMenu");
      contextMenu.hidePopup();
    }
  );
});

/**
 * Search for a login by it's username.
 *
 * Only unique login/origin combinations should be used at this test.
 */
function getLoginFromUsername(username) {
  return loginList().find(login => login.username == username);
}

/**
 * List of logins used for the test.
 *
 * We should only use unique usernames in this test,
 * because we need to search logins by username. There is one duplicate u+p combo
 * in order to test de-duping in the menu.
 */
function loginList() {
  return [
    LoginTestUtils.testData.formLogin({
      origin: "https://example.com",
      formActionOrigin: "https://example.com",
      username: "username",
      password: "password",
    }),
    // Same as above but HTTP in order to test de-duping.
    LoginTestUtils.testData.formLogin({
      origin: "http://example.com",
      formActionOrigin: "http://example.com",
      username: "username",
      password: "password",
    }),
    LoginTestUtils.testData.formLogin({
      origin: "http://example.com",
      formActionOrigin: "http://example.com",
      username: "username1",
      password: "password1",
    }),
    LoginTestUtils.testData.formLogin({
      origin: "https://example.com",
      formActionOrigin: "https://example.com",
      username: "username2",
      password: "password2",
    }),
    LoginTestUtils.testData.formLogin({
      origin: "http://example.org",
      formActionOrigin: "http://example.org",
      username: "username-cross-origin",
      password: "password-cross-origin",
    }),
  ];
}