From 5b116358872fcc2501df4902eade992b4a3a96b2 Mon Sep 17 00:00:00 2001 From: martgil Date: Thu, 23 Jan 2025 15:37:48 +0800 Subject: [PATCH 1/4] Add UI change to add "Secure Reply All" --- extension/img/svgs/reply-all-icon.svg | 1 + extension/js/common/xss-safe-factory.ts | 12 +++++++++--- .../webmail/gmail/gmail-element-replacer.ts | 8 ++++---- extension/manifest.json | 1 + 4 files changed, 15 insertions(+), 7 deletions(-) create mode 100644 extension/img/svgs/reply-all-icon.svg diff --git a/extension/img/svgs/reply-all-icon.svg b/extension/img/svgs/reply-all-icon.svg new file mode 100644 index 00000000000..30828ebd030 --- /dev/null +++ b/extension/img/svgs/reply-all-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extension/js/common/xss-safe-factory.ts b/extension/js/common/xss-safe-factory.ts index 26a97152388..471ed1206e5 100644 --- a/extension/js/common/xss-safe-factory.ts +++ b/extension/js/common/xss-safe-factory.ts @@ -269,9 +269,15 @@ export class XssSafeFactory { `; }; - public actionsMenuBtn = (action: 'reply' | 'forward') => { - return `
- secure ${action} + public actionsMenuBtn = (replyOption: ReplyOption) => { + const actionText = replyOption.replace('a_', '').replace('_', ' '); + const action = { + underscore: actionText.replace(' ', '_'), + hyphen: actionText.replace(' ', '-'), + }; + // * The action_${action.underscoreSeparated}_message_button is used as an identifier in GmailElementReplacer.actionActivateSecureReplyHandler() + return `
+ secure ${actionText}
`; }; diff --git a/extension/js/content_scripts/webmail/gmail/gmail-element-replacer.ts b/extension/js/content_scripts/webmail/gmail/gmail-element-replacer.ts index f2775edc7f4..8413bbc41d1 100644 --- a/extension/js/content_scripts/webmail/gmail/gmail-element-replacer.ts +++ b/extension/js/content_scripts/webmail/gmail/gmail-element-replacer.ts @@ -281,9 +281,9 @@ export class GmailElementReplacer extends WebmailElementReplacer { return !!$('iframe.pgp_block').filter(':visible').length; }; - private addMenuButton = (action: 'reply' | 'forward', selector: string) => { + private addMenuButton = (replyOption: ReplyOption, selector: string) => { const gmailActionsMenuContainer = $(this.sel.msgActionsMenu).find(selector); - const button = $(this.factory.actionsMenuBtn(action)).insertAfter(gmailActionsMenuContainer); // xss-safe-factory + const button = $(this.factory.actionsMenuBtn(replyOption)).insertAfter(gmailActionsMenuContainer); // xss-safe-factory button.on( 'click', Ui.event.handle((el, ev: JQuery.Event) => this.actionActivateSecureReplyHandler(el, ev)) @@ -292,8 +292,8 @@ export class GmailElementReplacer extends WebmailElementReplacer { private replaceActionsMenu = () => { if ($('.action_menu_message_button').length <= 0) { - this.addMenuButton('reply', '#r'); - this.addMenuButton('forward', '#r3'); + this.addMenuButton('a_reply', '#r'); + this.addMenuButton('a_forward', '#r3'); } }; diff --git a/extension/manifest.json b/extension/manifest.json index 8c57be8e8c8..176223d2b23 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -78,6 +78,7 @@ "resources": [ "/css/webmail.css", "/img/svgs/reply-icon.svg", + "/img/svgs/reply-all-icon.svg", "/img/svgs/forward-icon.svg", "/img/svgs/spinner-white-small.svg", "/img/svgs/spinner-green-small.svg", From 2a457f7a95eea3a207e68c20b0c6d750f5d0b5ab Mon Sep 17 00:00:00 2001 From: martgil Date: Thu, 23 Jan 2025 16:40:17 +0800 Subject: [PATCH 2/4] add comment + ready for incoming merge conflict --- .../webmail/gmail/gmail-element-replacer.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/extension/js/content_scripts/webmail/gmail/gmail-element-replacer.ts b/extension/js/content_scripts/webmail/gmail/gmail-element-replacer.ts index 8413bbc41d1..bd8cb7d3667 100644 --- a/extension/js/content_scripts/webmail/gmail/gmail-element-replacer.ts +++ b/extension/js/content_scripts/webmail/gmail/gmail-element-replacer.ts @@ -293,6 +293,8 @@ export class GmailElementReplacer extends WebmailElementReplacer { private replaceActionsMenu = () => { if ($('.action_menu_message_button').length <= 0) { this.addMenuButton('a_reply', '#r'); + // * when adding the reply_all button, check if #r2, the placeholder for reply_all, is visible + // * otherwise, it's not wise adding reply_all for single recipient emails this.addMenuButton('a_forward', '#r3'); } }; @@ -368,7 +370,14 @@ export class GmailElementReplacer extends WebmailElementReplacer { private actionActivateSecureReplyHandler = async (btn: HTMLElement, event: JQuery.Event) => { event.stopImmediatePropagation(); const secureReplyInvokedFromMenu = btn.className.includes('action_menu_message_button'); - const replyOption: ReplyOption = btn.className.includes('reply') ? 'a_reply' : 'a_forward'; + let replyOption: ReplyOption; + if (btn.className.includes('reply-all')) { + replyOption = 'a_reply_all'; + } else if (btn.className.includes('forward')) { + replyOption = 'a_forward'; + } else { + replyOption = 'a_reply'; + } if ($('#switch_to_encrypted_reply').length) { $('#switch_to_encrypted_reply').trigger('click'); return; From 72803ff42cf39530dd188bc53f7dbdf22dc0188f Mon Sep 17 00:00:00 2001 From: martgil Date: Fri, 24 Jan 2025 09:34:18 +0800 Subject: [PATCH 3/4] add checking before adding the button to avoid unncessary button --- .../webmail/gmail/gmail-element-replacer.ts | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/extension/js/content_scripts/webmail/gmail/gmail-element-replacer.ts b/extension/js/content_scripts/webmail/gmail/gmail-element-replacer.ts index 16cd8845ac2..48abe4c3eb1 100644 --- a/extension/js/content_scripts/webmail/gmail/gmail-element-replacer.ts +++ b/extension/js/content_scripts/webmail/gmail/gmail-element-replacer.ts @@ -151,8 +151,9 @@ export class GmailElementReplacer extends WebmailElementReplacer { $(document).on('click', 'div.aHU.hx', event => { const $actionsBtn = $(event.currentTarget).find(this.sel.msgActionsBtn); if ($actionsBtn.length && !$('.action_menu_message_button').length) { - this.addMenuButton('reply', '#r'); - this.addMenuButton('forward', '#r3'); + this.addMenuButton('a_reply', '#r'); + this.addMenuButton('a_reply_all', '#r2'); + this.addMenuButton('a_forward', '#r3'); } }); }; @@ -292,19 +293,12 @@ export class GmailElementReplacer extends WebmailElementReplacer { private addMenuButton = (replyOption: ReplyOption, selector: string) => { const gmailActionsMenuContainer = $(this.sel.msgActionsMenu).find(selector); - const button = $(this.factory.actionsMenuBtn(replyOption)).insertAfter(gmailActionsMenuContainer); // xss-safe-factory - button.on( - 'click', - Ui.event.handle((el, ev: JQuery.Event) => this.actionActivateSecureReplyHandler(el, ev)) - ); - }; - - private replaceActionsMenu = () => { - if ($('.action_menu_message_button').length <= 0) { - this.addMenuButton('a_reply', '#r'); - // * when adding the reply_all button, check if #r2, the placeholder for reply_all, is visible - // * otherwise, it's not wise adding reply_all for single recipient emails - this.addMenuButton('a_forward', '#r3'); + if ($(selector).css('display') === 'block') { + const button = $(this.factory.actionsMenuBtn(replyOption)).insertAfter(gmailActionsMenuContainer); // xss-safe-factory + button.on( + 'click', + Ui.event.handle((el, ev: JQuery.Event) => this.actionActivateSecureReplyHandler(el, ev)) + ); } }; From eca63a753d00aad0a2469695cb7e56b54408ee06 Mon Sep 17 00:00:00 2001 From: martgil Date: Fri, 24 Jan 2025 10:45:17 +0800 Subject: [PATCH 4/4] update gmail test --- test/source/tests/gmail.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/test/source/tests/gmail.ts b/test/source/tests/gmail.ts index b360f2d0df8..fe76f69adcb 100644 --- a/test/source/tests/gmail.ts +++ b/test/source/tests/gmail.ts @@ -463,22 +463,21 @@ export const defineGmailTests = (testVariant: TestVariant, testWithBrowser: Test await BrowserRecipe.setUpCommonAcct(t, browser, 'ci.tests.gmail'); const gmailPage = await openGmailPage(t, browser); await gotoGmailPage(gmailPage, '/FMfcgzGtwgfMhWTlgRwwKWzRhqNZzwXz'); // go to encrypted convo - await Util.sleep(5); const actionsMenuSelector = '.J-J5-Ji.aap'; await gmailPage.waitAndClick(actionsMenuSelector); - await Util.sleep(3); expect(await gmailPage.isElementPresent('@action-reply-message-button')); + expect(await gmailPage.isElementPresent('@action-reply-all-message-button')); + expect(await gmailPage.isElementPresent('@action-forward-message-button')); await gmailPage.waitAndClick('@action-reply-message-button'); const replyBox = await gmailPage.getFrame(['/chrome/elements/compose.htm'], { sleep: 5 }); - await Util.sleep(3); await replyBox.waitForContent('@input-body', ''); await gmailPage.waitAndClick(actionsMenuSelector); - await Util.sleep(3); - expect(await gmailPage.isElementPresent('@action-forward-message-button')); - await gmailPage.waitAndClick('@action-forward-message-button'); + await gmailPage.waitAndClick('@action-reply-all-message-button'); const replyBox2 = await gmailPage.getFrame(['/chrome/elements/compose.htm'], { sleep: 5 }); - await Util.sleep(3); - await replyBox2.waitForContent('@input-body', '---------- Forwarded message ---------'); + await replyBox2.waitForContent('@input-body', ''); + await gmailPage.waitAndClick('@action-forward-message-button'); + const replyBox3 = await gmailPage.getFrame(['/chrome/elements/compose.htm'], { sleep: 5 }); + await replyBox3.waitForContent('@input-body', '---------- Forwarded message ---------'); }) );