Skip to content

Commit 77c1380

Browse files
committed
Bug 1948261 - Add "Pin extension to toolbar" checkbox in postinstall r=zombie,fluent-reviewers,bolsson
This adds the "Pin extension to toolbar" checkbox to the post-install doorhanger, and ensures that the checkbox has a state that reflects the actual placement of the button, including externally triggered changes. Differential Revision: https://phabricator.services.mozilla.com/D250324 UltraBlame original commit: 0bf70c61d7daead1a5de390050ac529158ec0f1a
1 parent b479d95 commit 77c1380

File tree

5 files changed

+472
-1
lines changed

5 files changed

+472
-1
lines changed

browser/base/content/browser-addons.js

Lines changed: 147 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const lazy = {};
1515
ChromeUtils.defineESModuleGetters(lazy, {
1616
AMBrowserExtensionsImport: "resource://gre/modules/AddonManager.sys.mjs",
1717
AbuseReporter: "resource://gre/modules/AbuseReporter.sys.mjs",
18+
ExtensionCommon: "resource://gre/modules/ExtensionCommon.sys.mjs",
1819
ExtensionParent: "resource://gre/modules/ExtensionParent.sys.mjs",
1920
ExtensionPermissions: "resource://gre/modules/ExtensionPermissions.sys.mjs",
2021
OriginControls: "resource://gre/modules/ExtensionPermissions.sys.mjs",
@@ -737,19 +738,104 @@ customElements.define(
737738
}
738739
);
739740

741+
class BrowserActionWidgetObserver {
742+
#connected = false;
743+
744+
745+
746+
747+
748+
749+
constructor(addonId, onButtonAreaChanged) {
750+
this.addonId = addonId;
751+
752+
753+
this.widgetId = `${lazy.ExtensionCommon.makeWidgetId(addonId)}-browser-action`;
754+
this.onButtonAreaChanged = onButtonAreaChanged;
755+
}
756+
757+
startObserving() {
758+
if (this.#connected) {
759+
return;
760+
}
761+
this.#connected = true;
762+
CustomizableUI.addListener(this);
763+
window.addEventListener("unload", this);
764+
}
765+
766+
stopObserving() {
767+
if (!this.#connected) {
768+
return;
769+
}
770+
this.#connected = false;
771+
CustomizableUI.removeListener(this);
772+
window.removeEventListener("unload", this);
773+
}
774+
775+
hasBrowserActionUI() {
776+
const policy = WebExtensionPolicy.getByID(this.addonId);
777+
if (!policy?.canAccessWindow(window)) {
778+
779+
780+
return false;
781+
}
782+
if (!gUnifiedExtensions.browserActionFor(policy)) {
783+
784+
return false;
785+
}
786+
return true;
787+
}
788+
789+
onWidgetCreated(aWidgetId) {
790+
791+
792+
793+
if (aWidgetId === this.widgetId) {
794+
this.onButtonAreaChanged();
795+
}
796+
}
797+
798+
onWidgetAdded(aWidgetId) {
799+
if (aWidgetId === this.widgetId) {
800+
this.onButtonAreaChanged();
801+
}
802+
}
803+
804+
onWidgetMoved(aWidgetId) {
805+
if (aWidgetId === this.widgetId) {
806+
this.onButtonAreaChanged();
807+
}
808+
}
809+
810+
handleEvent(event) {
811+
if (event.type === "unload") {
812+
this.stopObserving();
813+
}
814+
}
815+
}
816+
740817
customElements.define(
741818
"addon-installed-notification",
742819
class MozAddonInstalledNotification extends customElements.get(
743820
"popupnotification"
744821
) {
822+
#shouldIgnoreCheckboxStateChangeEvent = false;
823+
#browserActionWidgetObserver;
745824
connectedCallback() {
746825
this.descriptionEl = this.querySelector("#addon-install-description");
826+
this.pinExtensionEl = this.querySelector(
827+
"#addon-pin-toolbarbutton-checkbox"
828+
);
747829

748830
this.addEventListener("click", this);
831+
this.pinExtensionEl.addEventListener("CheckboxStateChange", this);
832+
this.#browserActionWidgetObserver?.startObserving();
749833
}
750834

751835
disconnectedCallback() {
752836
this.removeEventListener("click", this);
837+
this.pinExtensionEl.removeEventListener("CheckboxStateChange", this);
838+
this.#browserActionWidgetObserver?.stopObserving();
753839
}
754840

755841
get #settingsLinkId() {
@@ -763,13 +849,19 @@ customElements.define(
763849
case "click": {
764850
if (target.id === this.#settingsLinkId) {
765851
const { addonId } = this.notification.options.customElementOptions;
766-
767852
BrowserAddonUI.openAddonsMgr(
768853
"addons://detail/" + encodeURIComponent(addonId)
769854
);
770855
}
771856
break;
772857
}
858+
case "CheckboxStateChange":
859+
860+
861+
if (!this.#shouldIgnoreCheckboxStateChangeEvent) {
862+
this.#handlePinnedCheckboxStateChange();
863+
}
864+
break;
773865
}
774866
}
775867

@@ -786,7 +878,16 @@ customElements.define(
786878
);
787879
}
788880

881+
this.#browserActionWidgetObserver?.stopObserving();
882+
this.#browserActionWidgetObserver = new BrowserActionWidgetObserver(
883+
this.notification.options.customElementOptions.addonId,
884+
() => this.#renderPinToolbarButtonCheckbox()
885+
);
886+
789887
this.render();
888+
if (this.isConnected) {
889+
this.#browserActionWidgetObserver.startObserving();
890+
}
790891
}
791892

792893
render() {
@@ -808,6 +909,7 @@ customElements.define(
808909
}
809910

810911
this.ownerDocument.l10n.setAttributes(this.descriptionEl, fluentId);
912+
this.#renderPinToolbarButtonCheckbox();
811913
}
812914

813915
get #dataCollectionPermissionsEnabled() {
@@ -816,6 +918,50 @@ customElements.define(
816918
false
817919
);
818920
}
921+
922+
#renderPinToolbarButtonCheckbox() {
923+
924+
925+
926+
this.pinExtensionEl.hidden = true;
927+
928+
if (!this.#browserActionWidgetObserver.hasBrowserActionUI()) {
929+
return;
930+
}
931+
const widgetId = this.#browserActionWidgetObserver.widgetId;
932+
933+
934+
935+
936+
937+
938+
939+
const area = CustomizableUI.getPlacementOfWidget(widgetId)?.area;
940+
let shouldPinToToolbar = area !== CustomizableUI.AREA_ADDONS;
941+
if (shouldPinToToolbar && area !== CustomizableUI.AREA_NAVBAR) {
942+
943+
return;
944+
}
945+
this.#shouldIgnoreCheckboxStateChangeEvent = true;
946+
this.pinExtensionEl.checked = shouldPinToToolbar;
947+
this.#shouldIgnoreCheckboxStateChangeEvent = false;
948+
this.pinExtensionEl.hidden = false;
949+
}
950+
951+
#handlePinnedCheckboxStateChange() {
952+
if (!this.#browserActionWidgetObserver.hasBrowserActionUI()) {
953+
954+
955+
const { addonId } = this.notification.options.customElementOptions;
956+
throw new Error(`No browser action widget found for ${addonId}!`);
957+
}
958+
const widgetId = this.#browserActionWidgetObserver.widgetId;
959+
const shouldPinToToolbar = this.pinExtensionEl.checked;
960+
if (shouldPinToToolbar) {
961+
gUnifiedExtensions._maybeMoveWidgetNodeBack(widgetId);
962+
}
963+
gUnifiedExtensions.pinToToolbar(widgetId, shouldPinToToolbar);
964+
}
819965
},
820966
{ extends: "popupnotification" }
821967
);

browser/components/customizableui/content/panelUI.inc.xhtml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,8 @@
225225
hidden="true">
226226
<popupnotificationcontent class="addon-installed-notification-content" orient="vertical">
227227
<description id="addon-install-description"></description>
228+
<checkbox id="addon-pin-toolbarbutton-checkbox"
229+
data-lazy-l10n-id="appmenu-addon-post-install-pin-toolbarbutton-checkbox"/>
228230
</popupnotificationcontent>
229231
</popupnotification>
230232

browser/components/extensions/test/browser/browser.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,8 @@ skip-if = [
762762

763763
["browser_unified_extensions_doorhangers.js"]
764764

765+
["browser_unified_extensions_doorhangers_postinstall.js"]
766+
765767
["browser_unified_extensions_item_messagebar.js"]
766768

767769
["browser_unified_extensions_messages.js"]

0 commit comments

Comments
 (0)