зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1578736 - Wrong context menu is displayed when right click on the website's link r=jaws
Differential Revision: https://phabricator.services.mozilla.com/D62842 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
ee067a4465
Коммит
71dcb2ac84
|
@ -133,12 +133,6 @@ class AboutLoginsChild extends JSWindowActorChild {
|
||||||
this.sendAsyncMessage("AboutLogins:OpenPreferences");
|
this.sendAsyncMessage("AboutLogins:OpenPreferences");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "AboutLoginsOpenSite": {
|
|
||||||
this.sendAsyncMessage("AboutLogins:OpenSite", {
|
|
||||||
login: event.detail,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "AboutLoginsRecordTelemetryEvent": {
|
case "AboutLoginsRecordTelemetryEvent": {
|
||||||
let { method, object, extra = {} } = event.detail;
|
let { method, object, extra = {} } = event.detail;
|
||||||
|
|
||||||
|
|
|
@ -313,23 +313,6 @@ class AboutLoginsParent extends JSWindowActorParent {
|
||||||
ownerGlobal.openPreferences("privacy-logins");
|
ownerGlobal.openPreferences("privacy-logins");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "AboutLogins:OpenSite": {
|
|
||||||
let guid = message.data.login.guid;
|
|
||||||
let logins = LoginHelper.searchLoginsWithObject({ guid });
|
|
||||||
if (logins.length != 1) {
|
|
||||||
log.warn(
|
|
||||||
`AboutLogins:OpenSite: expected to find a login for guid: ${guid} but found ${
|
|
||||||
logins.length
|
|
||||||
}`
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ownerGlobal.openWebLinkIn(logins[0].origin, "tab", {
|
|
||||||
relatedToCurrent: true,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "AboutLogins:MasterPasswordRequest": {
|
case "AboutLogins:MasterPasswordRequest": {
|
||||||
// This does no harm if master password isn't set.
|
// This does no harm if master password isn't set.
|
||||||
let tokendb = Cc["@mozilla.org/security/pk11tokendb;1"].createInstance(
|
let tokendb = Cc["@mozilla.org/security/pk11tokendb;1"].createInstance(
|
||||||
|
|
|
@ -186,11 +186,11 @@
|
||||||
size on page load since it always starts readonly. -->
|
size on page load since it always starts readonly. -->
|
||||||
<input type="url"
|
<input type="url"
|
||||||
name="origin"
|
name="origin"
|
||||||
class="origin-input"
|
|
||||||
required
|
required
|
||||||
data-l10n-id="login-item-origin"
|
data-l10n-id="login-item-origin"
|
||||||
dir="auto"
|
dir="auto"
|
||||||
readonly/>
|
readonly/>
|
||||||
|
<a class="origin-input" dir="auto" target="_blank" rel="noreferrer" name="origin" href=""></a>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-row">
|
<div class="detail-row">
|
||||||
|
|
|
@ -51,6 +51,9 @@ export default class LoginItem extends HTMLElement {
|
||||||
);
|
);
|
||||||
this._form = this.shadowRoot.querySelector("form");
|
this._form = this.shadowRoot.querySelector("form");
|
||||||
this._originInput = this.shadowRoot.querySelector("input[name='origin']");
|
this._originInput = this.shadowRoot.querySelector("input[name='origin']");
|
||||||
|
this._originDisplayInput = this.shadowRoot.querySelector(
|
||||||
|
"a[name='origin']"
|
||||||
|
);
|
||||||
this._usernameInput = this.shadowRoot.querySelector(
|
this._usernameInput = this.shadowRoot.querySelector(
|
||||||
"input[name='username']"
|
"input[name='username']"
|
||||||
);
|
);
|
||||||
|
@ -100,6 +103,7 @@ export default class LoginItem extends HTMLElement {
|
||||||
this._originInput.addEventListener("click", this);
|
this._originInput.addEventListener("click", this);
|
||||||
this._originInput.addEventListener("mousedown", this, true);
|
this._originInput.addEventListener("mousedown", this, true);
|
||||||
this._originInput.addEventListener("auxclick", this);
|
this._originInput.addEventListener("auxclick", this);
|
||||||
|
this._originDisplayInput.addEventListener("click", this);
|
||||||
this._revealCheckbox.addEventListener("click", this);
|
this._revealCheckbox.addEventListener("click", this);
|
||||||
window.addEventListener("AboutLoginsInitialLoginSelected", this);
|
window.addEventListener("AboutLoginsInitialLoginSelected", this);
|
||||||
window.addEventListener("AboutLoginsLoadInitialFavicon", this);
|
window.addEventListener("AboutLoginsLoadInitialFavicon", this);
|
||||||
|
@ -169,6 +173,11 @@ export default class LoginItem extends HTMLElement {
|
||||||
this._title.textContent = this._login.title;
|
this._title.textContent = this._login.title;
|
||||||
this._title.title = this._login.title;
|
this._title.title = this._login.title;
|
||||||
this._originInput.defaultValue = this._login.origin || "";
|
this._originInput.defaultValue = this._login.origin || "";
|
||||||
|
if (this._login.origin) {
|
||||||
|
// Creates anchor element with origin URL
|
||||||
|
this._originDisplayInput.href = this._login.origin || "";
|
||||||
|
this._originDisplayInput.innerText = this._login.origin || "";
|
||||||
|
}
|
||||||
this._usernameInput.defaultValue = this._login.username || "";
|
this._usernameInput.defaultValue = this._login.username || "";
|
||||||
if (this._login.password) {
|
if (this._login.password) {
|
||||||
// We use .value instead of .defaultValue since the latter updates the
|
// We use .value instead of .defaultValue since the latter updates the
|
||||||
|
@ -205,6 +214,7 @@ export default class LoginItem extends HTMLElement {
|
||||||
: "login-item-save-changes-button"
|
: "login-item-save-changes-button"
|
||||||
);
|
);
|
||||||
this._updatePasswordRevealState();
|
this._updatePasswordRevealState();
|
||||||
|
this._updateOriginDisplayState();
|
||||||
}
|
}
|
||||||
|
|
||||||
setBreaches(breachesByLoginGUID) {
|
setBreaches(breachesByLoginGUID) {
|
||||||
|
@ -680,13 +690,6 @@ export default class LoginItem extends HTMLElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleOriginClick() {
|
_handleOriginClick() {
|
||||||
document.dispatchEvent(
|
|
||||||
new CustomEvent("AboutLoginsOpenSite", {
|
|
||||||
bubbles: true,
|
|
||||||
detail: this._login,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
this._recordTelemetryEvent({
|
this._recordTelemetryEvent({
|
||||||
object: "existing_login",
|
object: "existing_login",
|
||||||
method: "open_site",
|
method: "open_site",
|
||||||
|
@ -811,5 +814,15 @@ export default class LoginItem extends HTMLElement {
|
||||||
this._passwordInput.remove();
|
this._passwordInput.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_updateOriginDisplayState() {
|
||||||
|
// Switches between the origin input and anchor tag depending
|
||||||
|
// if a new login is being created.
|
||||||
|
if (this.dataset.editing) {
|
||||||
|
this._originDisplayInput.replaceWith(this._originInput);
|
||||||
|
} else {
|
||||||
|
this._originInput.replaceWith(this._originDisplayInput);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
customElements.define("login-item", LoginItem);
|
customElements.define("login-item", LoginItem);
|
||||||
|
|
|
@ -30,7 +30,7 @@ add_task(async function test_launch_login_item() {
|
||||||
"discard-changes confirmation-dialog should be hidden before opening the site"
|
"discard-changes confirmation-dialog should be hidden before opening the site"
|
||||||
);
|
);
|
||||||
|
|
||||||
let originInput = loginItem.shadowRoot.querySelector(".origin-input");
|
let originInput = loginItem.shadowRoot.querySelector("a[name='origin']");
|
||||||
let EventUtils = ContentTaskUtils.getEventUtils(content);
|
let EventUtils = ContentTaskUtils.getEventUtils(content);
|
||||||
// Use synthesizeMouseAtCenter to generate an event that more closely resembles the
|
// Use synthesizeMouseAtCenter to generate an event that more closely resembles the
|
||||||
// properties of the event object that will be seen when the user clicks the element
|
// properties of the event object that will be seen when the user clicks the element
|
||||||
|
|
|
@ -70,7 +70,7 @@ add_task(async function setup() {
|
||||||
|
|
||||||
add_task(async function test_empty_item() {
|
add_task(async function test_empty_item() {
|
||||||
ok(gLoginItem, "loginItem exists");
|
ok(gLoginItem, "loginItem exists");
|
||||||
is(gLoginItem.shadowRoot.querySelector("input[name='origin']").value, "", "origin should be blank");
|
is(gLoginItem.shadowRoot.querySelector("a[name='origin']").getAttribute("href"), "", "origin should be blank");
|
||||||
is(gLoginItem.shadowRoot.querySelector("input[name='username']").value, "", "username should be blank");
|
is(gLoginItem.shadowRoot.querySelector("input[name='username']").value, "", "username should be blank");
|
||||||
is(gLoginItem._passwordInput.value, "", "password should be blank");
|
is(gLoginItem._passwordInput.value, "", "password should be blank");
|
||||||
ok(!gLoginItem._passwordInput.isConnected, "Real password input should be disconnected");
|
ok(!gLoginItem._passwordInput.isConnected, "Real password input should be disconnected");
|
||||||
|
@ -87,8 +87,8 @@ add_task(async function test_set_login() {
|
||||||
|
|
||||||
ok(!gLoginItem.dataset.editing, "loginItem should not be in 'edit' mode");
|
ok(!gLoginItem.dataset.editing, "loginItem should not be in 'edit' mode");
|
||||||
ok(!gLoginItem.dataset.isNewLogin, "loginItem should not be in 'isNewLogin' mode");
|
ok(!gLoginItem.dataset.isNewLogin, "loginItem should not be in 'isNewLogin' mode");
|
||||||
let originInput = gLoginItem.shadowRoot.querySelector("input[name='origin']");
|
let originLink = gLoginItem.shadowRoot.querySelector("a[name='origin']");
|
||||||
is(originInput.value, TEST_LOGIN_1.origin, "origin should be populated");
|
is(originLink.getAttribute("href"), TEST_LOGIN_1.origin, "origin should be populated");
|
||||||
let usernameInput = gLoginItem.shadowRoot.querySelector("input[name='username']");
|
let usernameInput = gLoginItem.shadowRoot.querySelector("input[name='username']");
|
||||||
is(usernameInput.value, TEST_LOGIN_1.username, "username should be populated");
|
is(usernameInput.value, TEST_LOGIN_1.username, "username should be populated");
|
||||||
is(document.l10n.getAttributes(usernameInput).id, "about-logins-login-item-username", "username field should have default placeholder when not editing");
|
is(document.l10n.getAttributes(usernameInput).id, "about-logins-login-item-username", "username field should have default placeholder when not editing");
|
||||||
|
@ -107,27 +107,6 @@ add_task(async function test_set_login() {
|
||||||
let copyButtons = [...gLoginItem.shadowRoot.querySelectorAll(".copy-button")];
|
let copyButtons = [...gLoginItem.shadowRoot.querySelectorAll(".copy-button")];
|
||||||
ok(copyButtons.every(button => !isHidden(button)), "The copy buttons should be visible when viewing a login");
|
ok(copyButtons.every(button => !isHidden(button)), "The copy buttons should be visible when viewing a login");
|
||||||
|
|
||||||
let openSiteEventDispatched = false;
|
|
||||||
document.addEventListener("AboutLoginsOpenSite", event => {
|
|
||||||
is(event.detail.guid, TEST_LOGIN_1.guid, "event should include guid");
|
|
||||||
openSiteEventDispatched = true;
|
|
||||||
}, {once: true});
|
|
||||||
originInput.click();
|
|
||||||
ok(openSiteEventDispatched, "Clicking the .origin-input should dispatch the AboutLoginsOpenSite event");
|
|
||||||
|
|
||||||
openSiteEventDispatched = false;
|
|
||||||
document.addEventListener("AboutLoginsOpenSite", event => {
|
|
||||||
is(event.detail.guid, TEST_LOGIN_1.guid, "event should include guid");
|
|
||||||
openSiteEventDispatched = true;
|
|
||||||
}, {once: true});
|
|
||||||
synthesizeMouseAtCenter(originInput, {button: 1});
|
|
||||||
ok(openSiteEventDispatched, "Middle-clicking the .origin-input should dispatch the AboutLoginsOpenSite event");
|
|
||||||
|
|
||||||
document.addEventListener("AboutLoginsOpenSite", event => {
|
|
||||||
ok(false, "right-clicking the .origin-input should not trigger the AboutLoginsOpenSite event");
|
|
||||||
}, {once: true});
|
|
||||||
synthesizeMouseAtCenter(originInput, {button: 2});
|
|
||||||
|
|
||||||
let loginNoUsername = Object.assign({}, TEST_LOGIN_1, {username: ""});
|
let loginNoUsername = Object.assign({}, TEST_LOGIN_1, {username: ""});
|
||||||
gLoginItem.setLogin(loginNoUsername);
|
gLoginItem.setLogin(loginNoUsername);
|
||||||
ok(!gLoginItem.dataset.editing, "loginItem should not be in 'edit' mode");
|
ok(!gLoginItem.dataset.editing, "loginItem should not be in 'edit' mode");
|
||||||
|
@ -154,7 +133,7 @@ add_task(async function test_update_breaches() {
|
||||||
let correspondingBreach = TEST_BREACHES_MAP.get(gLoginItem._login.guid);
|
let correspondingBreach = TEST_BREACHES_MAP.get(gLoginItem._login.guid);
|
||||||
let breachAlert = gLoginItem.shadowRoot.querySelector(".breach-alert");
|
let breachAlert = gLoginItem.shadowRoot.querySelector(".breach-alert");
|
||||||
ok(!isHidden(breachAlert), "Breach alert should be visible");
|
ok(!isHidden(breachAlert), "Breach alert should be visible");
|
||||||
is(breachAlert.querySelector(".breach-alert-link").href, correspondingBreach.breachAlertURL, "Breach alert link should be equal to the correspondingBreach.breachAlertURL.");
|
is(breachAlert.querySelector(".breach-alert-link").getAttribute("href"), correspondingBreach.breachAlertURL, "Breach alert link should be equal to the correspondingBreach.breachAlertURL.");
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function test_breach_alert_is_correctly_hidden() {
|
add_task(async function test_breach_alert_is_correctly_hidden() {
|
||||||
|
@ -329,7 +308,7 @@ add_task(async function test_different_login_modified() {
|
||||||
gLoginItem.loginModified(otherLogin);
|
gLoginItem.loginModified(otherLogin);
|
||||||
await asyncElementRendered();
|
await asyncElementRendered();
|
||||||
|
|
||||||
is(gLoginItem.shadowRoot.querySelector("input[name='origin']").value, TEST_LOGIN_1.origin, "origin should be unchanged");
|
is(gLoginItem.shadowRoot.querySelector("a[name='origin']").getAttribute("href"), TEST_LOGIN_1.origin, "origin should be unchanged");
|
||||||
is(gLoginItem.shadowRoot.querySelector("input[name='username']").value, TEST_LOGIN_1.username, "username should be unchanged");
|
is(gLoginItem.shadowRoot.querySelector("input[name='username']").value, TEST_LOGIN_1.username, "username should be unchanged");
|
||||||
is(gLoginItem._passwordInput.value, TEST_LOGIN_1.password, "password should be unchanged");
|
is(gLoginItem._passwordInput.value, TEST_LOGIN_1.password, "password should be unchanged");
|
||||||
ok(!gLoginItem._passwordInput.hasAttribute("value"), "Password shouldn't be exposed in @value");
|
ok(!gLoginItem._passwordInput.hasAttribute("value"), "Password shouldn't be exposed in @value");
|
||||||
|
@ -347,7 +326,7 @@ add_task(async function test_different_login_removed() {
|
||||||
gLoginItem.loginRemoved(otherLogin);
|
gLoginItem.loginRemoved(otherLogin);
|
||||||
await asyncElementRendered();
|
await asyncElementRendered();
|
||||||
|
|
||||||
is(gLoginItem.shadowRoot.querySelector("input[name='origin']").value, TEST_LOGIN_1.origin, "origin should be unchanged");
|
is(gLoginItem.shadowRoot.querySelector("a[name='origin']").getAttribute("href"), TEST_LOGIN_1.origin, "origin should be unchanged");
|
||||||
is(gLoginItem.shadowRoot.querySelector("input[name='username']").value, TEST_LOGIN_1.username, "username should be unchanged");
|
is(gLoginItem.shadowRoot.querySelector("input[name='username']").value, TEST_LOGIN_1.username, "username should be unchanged");
|
||||||
is(gLoginItem._passwordInput.value, TEST_LOGIN_1.password, "password should be unchanged");
|
is(gLoginItem._passwordInput.value, TEST_LOGIN_1.password, "password should be unchanged");
|
||||||
ok(!gLoginItem._passwordInput.hasAttribute("value"), "Password shouldn't be exposed in @value");
|
ok(!gLoginItem._passwordInput.hasAttribute("value"), "Password shouldn't be exposed in @value");
|
||||||
|
@ -364,7 +343,7 @@ add_task(async function test_login_modified() {
|
||||||
gLoginItem.loginModified(modifiedLogin);
|
gLoginItem.loginModified(modifiedLogin);
|
||||||
await asyncElementRendered();
|
await asyncElementRendered();
|
||||||
|
|
||||||
is(gLoginItem.shadowRoot.querySelector("input[name='origin']").value, modifiedLogin.origin, "origin should be updated");
|
is(gLoginItem.shadowRoot.querySelector("a[name='origin']").getAttribute("href"), modifiedLogin.origin, "origin should be updated");
|
||||||
is(gLoginItem.shadowRoot.querySelector("input[name='username']").value, modifiedLogin.username, "username should be updated");
|
is(gLoginItem.shadowRoot.querySelector("input[name='username']").value, modifiedLogin.username, "username should be updated");
|
||||||
is(gLoginItem._passwordInput.value, modifiedLogin.password, "password should be updated");
|
is(gLoginItem._passwordInput.value, modifiedLogin.password, "password should be updated");
|
||||||
ok(!gLoginItem._passwordInput.hasAttribute("value"), "Password shouldn't be exposed in @value");
|
ok(!gLoginItem._passwordInput.hasAttribute("value"), "Password shouldn't be exposed in @value");
|
||||||
|
|
Загрузка…
Ссылка в новой задаче