mirror of
https://github.com/bitwarden/browser
synced 2025-12-14 15:23:33 +00:00
[PM-10897] Fixing invalid url reference when creating login ciphers from inline menu (#10527)
* [PM-10897] Fixing invalid url reference when creating login ciphers from inline menu * [PM-10897] Ensuring that a subframe that contains a full set of data for a login cipher is treated as authoritative
This commit is contained in:
@@ -1299,7 +1299,11 @@ describe("OverlayBackground", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
sender = mock<chrome.runtime.MessageSender>({ tab: { id: 1 } });
|
sender = mock<chrome.runtime.MessageSender>({
|
||||||
|
tab: { id: 1 },
|
||||||
|
url: "https://top-frame-test.com",
|
||||||
|
frameId: 0,
|
||||||
|
});
|
||||||
openAddEditVaultItemPopoutSpy = jest
|
openAddEditVaultItemPopoutSpy = jest
|
||||||
.spyOn(overlayBackground as any, "openAddEditVaultItemPopout")
|
.spyOn(overlayBackground as any, "openAddEditVaultItemPopout")
|
||||||
.mockImplementation();
|
.mockImplementation();
|
||||||
@@ -1482,10 +1486,15 @@ describe("OverlayBackground", () => {
|
|||||||
|
|
||||||
describe("pulling cipher data from multiple frames of a tab", () => {
|
describe("pulling cipher data from multiple frames of a tab", () => {
|
||||||
let subFrameSender: MockProxy<chrome.runtime.MessageSender>;
|
let subFrameSender: MockProxy<chrome.runtime.MessageSender>;
|
||||||
|
let secondSubFrameSender: MockProxy<chrome.runtime.MessageSender>;
|
||||||
const command = "autofillOverlayAddNewVaultItem";
|
const command = "autofillOverlayAddNewVaultItem";
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
subFrameSender = mock<chrome.runtime.MessageSender>({ tab: sender.tab, frameId: 2 });
|
subFrameSender = mock<chrome.runtime.MessageSender>({ tab: sender.tab, frameId: 2 });
|
||||||
|
secondSubFrameSender = mock<chrome.runtime.MessageSender>({
|
||||||
|
tab: sender.tab,
|
||||||
|
frameId: 3,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("combines the login cipher data from all frames", async () => {
|
it("combines the login cipher data from all frames", async () => {
|
||||||
@@ -1494,9 +1503,15 @@ describe("OverlayBackground", () => {
|
|||||||
"buildLoginCipherView",
|
"buildLoginCipherView",
|
||||||
);
|
);
|
||||||
const addNewCipherType = CipherType.Login;
|
const addNewCipherType = CipherType.Login;
|
||||||
|
const topLevelLoginCipherData = {
|
||||||
|
uri: "https://top-frame-test.com",
|
||||||
|
hostname: "top-frame-test.com",
|
||||||
|
username: "",
|
||||||
|
password: "",
|
||||||
|
};
|
||||||
const loginCipherData = {
|
const loginCipherData = {
|
||||||
uri: "https://tacos.com",
|
uri: "https://tacos.com",
|
||||||
hostname: "",
|
hostname: "tacos.com",
|
||||||
username: "username",
|
username: "username",
|
||||||
password: "",
|
password: "",
|
||||||
};
|
};
|
||||||
@@ -1507,11 +1522,56 @@ describe("OverlayBackground", () => {
|
|||||||
password: "password",
|
password: "password",
|
||||||
};
|
};
|
||||||
|
|
||||||
sendMockExtensionMessage({ command, addNewCipherType, login: loginCipherData }, sender);
|
sendMockExtensionMessage(
|
||||||
|
{ command, addNewCipherType, login: topLevelLoginCipherData },
|
||||||
|
sender,
|
||||||
|
);
|
||||||
|
sendMockExtensionMessage(
|
||||||
|
{ command, addNewCipherType, login: loginCipherData },
|
||||||
|
subFrameSender,
|
||||||
|
);
|
||||||
sendMockExtensionMessage(
|
sendMockExtensionMessage(
|
||||||
{ command, addNewCipherType, login: subFrameLoginCipherData },
|
{ command, addNewCipherType, login: subFrameLoginCipherData },
|
||||||
|
secondSubFrameSender,
|
||||||
|
);
|
||||||
|
jest.advanceTimersByTime(100);
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
expect(buildLoginCipherViewSpy).toHaveBeenCalledWith({
|
||||||
|
uri: "https://top-frame-test.com",
|
||||||
|
hostname: "top-frame-test.com",
|
||||||
|
username: "username",
|
||||||
|
password: "password",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sets the uri to the subframe of a tab if the login data is complete", async () => {
|
||||||
|
const buildLoginCipherViewSpy = jest.spyOn(
|
||||||
|
overlayBackground as any,
|
||||||
|
"buildLoginCipherView",
|
||||||
|
);
|
||||||
|
const addNewCipherType = CipherType.Login;
|
||||||
|
const loginCipherData = {
|
||||||
|
uri: "https://tacos.com",
|
||||||
|
hostname: "tacos.com",
|
||||||
|
username: "username",
|
||||||
|
password: "password",
|
||||||
|
};
|
||||||
|
const topLevelLoginCipherData = {
|
||||||
|
uri: "https://top-frame-test.com",
|
||||||
|
hostname: "top-frame-test.com",
|
||||||
|
username: "",
|
||||||
|
password: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
sendMockExtensionMessage(
|
||||||
|
{ command, addNewCipherType, login: loginCipherData },
|
||||||
subFrameSender,
|
subFrameSender,
|
||||||
);
|
);
|
||||||
|
sendMockExtensionMessage(
|
||||||
|
{ command, addNewCipherType, login: topLevelLoginCipherData },
|
||||||
|
sender,
|
||||||
|
);
|
||||||
jest.advanceTimersByTime(100);
|
jest.advanceTimersByTime(100);
|
||||||
await flushPromises();
|
await flushPromises();
|
||||||
|
|
||||||
|
|||||||
@@ -1589,7 +1589,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (login && this.isAddingNewLogin()) {
|
if (login && this.isAddingNewLogin()) {
|
||||||
this.updateCurrentAddNewItemLogin(login);
|
this.updateCurrentAddNewItemLogin(login, sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (card && this.isAddingNewCard()) {
|
if (card && this.isAddingNewCard()) {
|
||||||
@@ -1629,22 +1629,56 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
* login data is already present, the data will be merged with the existing data.
|
* login data is already present, the data will be merged with the existing data.
|
||||||
*
|
*
|
||||||
* @param login - The login data captured from the extension message
|
* @param login - The login data captured from the extension message
|
||||||
|
* @param sender - The sender of the extension message
|
||||||
*/
|
*/
|
||||||
private updateCurrentAddNewItemLogin(login: NewLoginCipherData) {
|
private updateCurrentAddNewItemLogin(
|
||||||
|
login: NewLoginCipherData,
|
||||||
|
sender: chrome.runtime.MessageSender,
|
||||||
|
) {
|
||||||
|
const { username, password } = login;
|
||||||
|
|
||||||
|
if (this.partialLoginDataFoundInSubFrame(sender, login)) {
|
||||||
|
login.uri = "";
|
||||||
|
login.hostname = "";
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.currentAddNewItemData.login) {
|
if (!this.currentAddNewItemData.login) {
|
||||||
this.currentAddNewItemData.login = login;
|
this.currentAddNewItemData.login = login;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentLoginData = this.currentAddNewItemData.login;
|
const currentLoginData = this.currentAddNewItemData.login;
|
||||||
|
if (sender.frameId === 0 && currentLoginData.hostname && !username && !password) {
|
||||||
|
login.uri = "";
|
||||||
|
login.hostname = "";
|
||||||
|
}
|
||||||
|
|
||||||
this.currentAddNewItemData.login = {
|
this.currentAddNewItemData.login = {
|
||||||
uri: login.uri || currentLoginData.uri,
|
uri: login.uri || currentLoginData.uri,
|
||||||
hostname: login.hostname || currentLoginData.hostname,
|
hostname: login.hostname || currentLoginData.hostname,
|
||||||
username: login.username || currentLoginData.username,
|
username: username || currentLoginData.username,
|
||||||
password: login.password || currentLoginData.password,
|
password: password || currentLoginData.password,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles verifying if the login data for a tab is separated between various
|
||||||
|
* iframe elements. If that is the case, we want to ignore the login uri and
|
||||||
|
* domain to ensure the top frame is treated as the primary source of login data.
|
||||||
|
*
|
||||||
|
* @param sender - The sender of the extension message
|
||||||
|
* @param login - The login data captured from the extension message
|
||||||
|
*/
|
||||||
|
private partialLoginDataFoundInSubFrame(
|
||||||
|
sender: chrome.runtime.MessageSender,
|
||||||
|
login: NewLoginCipherData,
|
||||||
|
) {
|
||||||
|
const { frameId } = sender;
|
||||||
|
const { username, password } = login;
|
||||||
|
|
||||||
|
return frameId !== 0 && (!username || !password);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the current add new item data with the provided card data. If the
|
* Updates the current add new item data with the provided card data. If the
|
||||||
* card data is already present, the data will be merged with the existing data.
|
* card data is already present, the data will be merged with the existing data.
|
||||||
|
|||||||
Reference in New Issue
Block a user