diff --git a/locales/en-US/browser/browser/zen-general.ftl b/locales/en-US/browser/browser/zen-general.ftl index 708bc05d9..bea40c496 100644 --- a/locales/en-US/browser/browser/zen-general.ftl +++ b/locales/en-US/browser/browser/zen-general.ftl @@ -64,3 +64,6 @@ zen-icons-picker-svg = .label = Icons urlbar-search-mode-zen_actions = Actions +zen-site-data-settings = Settings + +zen-generic-manage = Manage diff --git a/src/browser/base/content/browser-addons-js.patch b/src/browser/base/content/browser-addons-js.patch index 318539af9..968b5f924 100644 --- a/src/browser/base/content/browser-addons-js.patch +++ b/src/browser/base/content/browser-addons-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/base/content/browser-addons.js b/browser/base/content/browser-addons.js -index d7542a38a0242dd9c9c6390171d59992d75a0c19..d20e5a9fa42c88c7ba28fac1ef13dd693f1f1135 100644 +index d7542a38a0242dd9c9c6390171d59992d75a0c19..e3bda9bc28aeca7258fcd91fa1a4719b4950e28b 100644 --- a/browser/base/content/browser-addons.js +++ b/browser/base/content/browser-addons.js @@ -1064,7 +1064,7 @@ var gXPInstallObserver = { @@ -20,7 +20,20 @@ index d7542a38a0242dd9c9c6390171d59992d75a0c19..d20e5a9fa42c88c7ba28fac1ef13dd69 }, }; -@@ -2608,7 +2608,7 @@ var gUnifiedExtensions = { +@@ -2509,11 +2509,7 @@ var gUnifiedExtensions = { + // Lazy load the unified-extensions-panel panel the first time we need to + // display it. + if (!this._panel) { +- let template = document.getElementById( +- "unified-extensions-panel-template" +- ); +- template.replaceWith(template.content); +- this._panel = document.getElementById("unified-extensions-panel"); ++ this._panel = document.getElementById("zen-unified-site-data-panel"); + let customizationArea = this._panel.querySelector( + "#unified-extensions-area" + ); +@@ -2608,7 +2604,7 @@ var gUnifiedExtensions = { this.recordButtonTelemetry(reason || "extensions_panel_showing"); this.ensureButtonShownBeforeAttachingPanel(panel); PanelMultiView.openPopup(panel, this._button, { @@ -29,7 +42,7 @@ index d7542a38a0242dd9c9c6390171d59992d75a0c19..d20e5a9fa42c88c7ba28fac1ef13dd69 triggerEvent: aEvent, }); } -@@ -2795,18 +2795,20 @@ var gUnifiedExtensions = { +@@ -2795,18 +2791,20 @@ var gUnifiedExtensions = { this._maybeMoveWidgetNodeBack(widgetId); } diff --git a/src/browser/base/content/zen-panels/site-data.inc b/src/browser/base/content/zen-panels/site-data.inc new file mode 100644 index 000000000..88ed567d3 --- /dev/null +++ b/src/browser/base/content/zen-panels/site-data.inc @@ -0,0 +1,65 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + \ No newline at end of file diff --git a/src/browser/base/content/zen-popupset.inc.xhtml b/src/browser/base/content/zen-popupset.inc.xhtml index 3a812435a..e58a85c4c 100644 --- a/src/browser/base/content/zen-popupset.inc.xhtml +++ b/src/browser/base/content/zen-popupset.inc.xhtml @@ -5,5 +5,6 @@ #include zen-panels/gradient-generator.inc #include zen-panels/emojis-picker.inc #include zen-panels/folders-search.inc +#include zen-panels/site-data.inc #include zen-panels/popups.inc diff --git a/src/browser/themes/shared/zen-icons/icons.css b/src/browser/themes/shared/zen-icons/icons.css index fec5a4d24..a7f516d8e 100644 --- a/src/browser/themes/shared/zen-icons/icons.css +++ b/src/browser/themes/shared/zen-icons/icons.css @@ -74,7 +74,8 @@ } #appMenu-zoom-controls, -#PanelUI-zen-gradient-generator-color-add { +#PanelUI-zen-gradient-generator-color-add, +#zen-site-data-new-addon-button { list-style-image: url('plus.svg') !important; } @@ -466,8 +467,14 @@ } /* permissions */ -#permissions-granted-icon { - list-style-image: url('permissions.svg') !important; +#identity-permission-box, +#identity-icon-box { + display: none !important; +} + +#zen-site-data-icon { + list-style-image: url('permissions.svg'); + -moz-context-properties: fill, fill-opacity; } .geo-icon { diff --git a/src/zen/common/ZenUIManager.mjs b/src/zen/common/ZenUIManager.mjs index c98f8fdca..78f17b3a2 100644 --- a/src/zen/common/ZenUIManager.mjs +++ b/src/zen/common/ZenUIManager.mjs @@ -1,6 +1,11 @@ // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. + +ChromeUtils.defineESModuleGetters(this, { + nsZenSiteDataPanel: 'resource:///modules/ZenSiteDataPanel.sys.mjs', +}); + var gZenUIManager = { _popupTrackingElements: [], _hoverPausedForExpand: false, @@ -14,19 +19,6 @@ var gZenUIManager = { init() { document.addEventListener('popupshowing', this.onPopupShowing.bind(this)); document.addEventListener('popuphidden', this.onPopupHidden.bind(this)); - XPCOMUtils.defineLazyPreferenceGetter( - this, - 'contentElementSeparation', - 'zen.theme.content-element-separation', - 0 - ); - XPCOMUtils.defineLazyPreferenceGetter(this, 'urlbarWaitToClear', 'zen.urlbar.wait-to-clear', 0); - XPCOMUtils.defineLazyPreferenceGetter( - this, - 'urlbarShowDomainOnly', - 'zen.urlbar.show-domain-only-in-sidebar', - true - ); document.addEventListener('mousedown', this.handleMouseDown.bind(this), true); @@ -44,6 +36,8 @@ var gZenUIManager = { return document.getElementById('zen-toast-container'); }); + window.gZenSiteDataPanel = new nsZenSiteDataPanel(window); + gURLBar._zenTrimURL = this.urlbarTrim.bind(this); new ResizeObserver( @@ -596,6 +590,26 @@ var gZenUIManager = { }, }; +XPCOMUtils.defineLazyPreferenceGetter( + gZenUIManager, + 'contentElementSeparation', + 'zen.theme.content-element-separation', + 0 +); + +XPCOMUtils.defineLazyPreferenceGetter( + gZenUIManager, + 'urlbarWaitToClear', + 'zen.urlbar.wait-to-clear', + 0 +); +XPCOMUtils.defineLazyPreferenceGetter( + gZenUIManager, + 'urlbarShowDomainOnly', + 'zen.urlbar.show-domain-only-in-sidebar', + true +); + var gZenVerticalTabsManager = { init() { this._multiWindowFeature = new nsZenMultiWindowFeature(); diff --git a/src/zen/common/styles/zen-omnibox.css b/src/zen/common/styles/zen-omnibox.css index 421641b4f..3be04ae0d 100644 --- a/src/zen/common/styles/zen-omnibox.css +++ b/src/zen/common/styles/zen-omnibox.css @@ -224,17 +224,7 @@ display: none; } - #identity-box:not([pageproxystate='invalid']):not(.notSecure) #identity-icon-box:not([open]) { - margin-inline-start: calc(-8px - 2 * var(--urlbar-icon-padding)); - transform: translateX(100%); - opacity: 0; - - :root:not([supress-primary-adjustment]) & { - transition: all 0.1s ease; - } - } - - #identity-permission-box > *:not(#permissions-granted-icon) { + #identity-permission-box > *:not(#zen-site-data-icon) { visibility: collapse; } @@ -242,25 +232,11 @@ display: none; } - #urlbar[open] - :is(#tracking-protection-icon-container, .urlbar-page-action, .identity-box-button):not( - [hidden] - ):not(#identity-permission-box), - #urlbar:hover #identity-icon-box { - opacity: 1 !important; - margin-inline-start: 0 !important; - transform: none !important; - display: flex; - #urlbar:not(:hover) & { - transition: none; - } - } - #urlbar:not([open]) #userContext-icons { margin-inline: 0; } - #urlbar:not([open]) { + #urlbar:not([breakout-extend='true']) { #identity-box:not([pageproxystate='invalid']) { order: 2; } diff --git a/src/zen/common/styles/zen-popup.css b/src/zen/common/styles/zen-popup.css index 5eceee4eb..ecc8b78f7 100644 --- a/src/zen/common/styles/zen-popup.css +++ b/src/zen/common/styles/zen-popup.css @@ -241,12 +241,6 @@ panel { margin-inline: 0; } -#identity-popup-mainView > toolbarseparator:first-child, -#unified-extensions-view > toolbarseparator:first-child { - display: none; - opacity: 0; -} - menupopup, panel { box-shadow: none; diff --git a/src/zen/common/styles/zen-single-components.css b/src/zen/common/styles/zen-single-components.css index 8bdaa80c0..1cc267dd5 100644 --- a/src/zen/common/styles/zen-single-components.css +++ b/src/zen/common/styles/zen-single-components.css @@ -261,3 +261,82 @@ body > #confetti { #customization-container { --toolbar-bgcolor: var(--zen-dialog-background); } + +/* Site Data popup */ + +#zen-unified-site-data-panel { + --panel-padding: 14px; + --panel-width: 250px; + --menu-panel-width-wide: calc(var(--panel-width) - var(--panel-padding) * 2); + --uei-icon-size: 16px; + --arrowpanel-menuitem-border-radius: 10px; +} + +#unified-extensions-messages-container { + display: none; +} + +#zen-site-data-addons { + display: flex; + flex-wrap: wrap; + gap: 6px; + + .unified-extensions-item-name, + .unified-extensions-item-message, + .unified-extensions-item-message-hover, + .unified-extensions-item-message-hover-menu-button, + .unified-extensions-item-menu-button { + display: none; + } + + #overflowed-extensions-list, + #unified-extensions-area, + .unified-extensions-list, + #zen-site-data-new-addon-button-container { + display: contents; + + &:empty { + display: none; + } + + & > * { + background-color: color-mix(in srgb, currentcolor 6%, transparent) !important; + width: 48px; + height: 32px; + margin: 0; + justify-content: center; + align-items: center; + border-radius: 6px; + + & .toolbarbutton-badge-stack { + margin: 0; + } + } + } +} + +.zen-site-data-section { + gap: 8px; + padding-bottom: 20px; +} + +.zen-site-data-section-header { + font-weight: 600; + + & label { + margin: 0; + } + + & > label:nth-child(2) { + transition: opacity 0.15s ease-in-out; + opacity: 0; + + .zen-site-data-section:hover & { + opacity: 0.8; + } + } +} + +#zen-site-data-new-addon-button .toolbarbutton-text { + display: none; +} diff --git a/src/zen/urlbar/ZenSiteDataPanel.sys.mjs b/src/zen/urlbar/ZenSiteDataPanel.sys.mjs new file mode 100644 index 000000000..d379c8f73 --- /dev/null +++ b/src/zen/urlbar/ZenSiteDataPanel.sys.mjs @@ -0,0 +1,163 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +export class nsZenSiteDataPanel { + constructor(window) { + this.window = window; + this.document = window.document; + + this.panel = this.document.getElementById('zen-unified-site-data-panel'); + this.#init(); + } + + #init() { + // Add a new button to the urlbar popup + const button = this.window.MozXULElement.parseXULToFragment(` + + + + `); + this.document.getElementById('identity-icon-box').after(button); + button.addEventListener('command', this); + + // Remove the old permissions dialog + this.document.getElementById('unified-extensions-panel-template').remove(); + } + + show() { + this.#preparePanel(); + } + + #preparePanel() { + this.#setSitePermissions(); + } + + #setSitePermissions() { + const { gBrowser, SitePermissions } = this.window; + const list = this.document.getElementById('zen-site-data-settings-list'); + const section = list.closest('.zen-site-data-section'); + + // show permission icons + let permissions = SitePermissions.getAllPermissionDetailsForBrowser(gBrowser.selectedBrowser); + + // Don't display origin-keyed 3rdPartyStorage permissions that are covered by + // site-keyed 3rdPartyFrameStorage permissions. + let thirdPartyStorageSites = new Set( + permissions + .map(function (permission) { + let [id, key] = permission.id.split(SitePermissions.PERM_KEY_DELIMITER); + if (id == '3rdPartyFrameStorage') { + return key; + } + return null; + }) + .filter(function (key) { + return key != null; + }) + ); + permissions = permissions.filter(function (permission) { + let [id, key] = permission.id.split(SitePermissions.PERM_KEY_DELIMITER); + if (id != '3rdPartyStorage') { + return true; + } + try { + let origin = Services.io.newURI(key); + let site = Services.eTLD.getSite(origin); + return !thirdPartyStorageSites.has(site); + } catch { + return false; + } + }); + + this._sharingState = gBrowser.selectedTab._sharingState; + + if (this._sharingState?.geo) { + let geoPermission = permissions.find((perm) => perm.id === 'geo'); + if (geoPermission) { + geoPermission.sharingState = true; + } else { + permissions.push({ + id: 'geo', + state: SitePermissions.ALLOW, + scope: SitePermissions.SCOPE_REQUEST, + sharingState: true, + }); + } + } + + if (this._sharingState?.xr) { + let xrPermission = permissions.find((perm) => perm.id === 'xr'); + if (xrPermission) { + xrPermission.sharingState = true; + } else { + permissions.push({ + id: 'xr', + state: SitePermissions.ALLOW, + scope: SitePermissions.SCOPE_REQUEST, + sharingState: true, + }); + } + } + + if (this._sharingState?.webRTC) { + let webrtcState = this._sharingState.webRTC; + // If WebRTC device or screen are in use, we need to find + // the associated ALLOW permission item to set the sharingState field. + for (let id of ['camera', 'microphone', 'screen']) { + if (webrtcState[id]) { + let found = false; + for (let permission of permissions) { + let [permId] = permission.id.split(SitePermissions.PERM_KEY_DELIMITER); + if (permId != id || permission.state != SitePermissions.ALLOW) { + continue; + } + found = true; + permission.sharingState = webrtcState[id]; + } + if (!found) { + // If the ALLOW permission item we were looking for doesn't exist, + // the user has temporarily allowed sharing and we need to add + // an item in the permissions array to reflect this. + permissions.push({ + id, + state: SitePermissions.ALLOW, + scope: SitePermissions.SCOPE_REQUEST, + sharingState: webrtcState[id], + }); + } + } + } + } + + list.innerHTML = ''; + let totalBlockedPopups = gBrowser.selectedBrowser.popupBlocker.getBlockedPopupCount(); + for (let permission of permissions) { + let [id, key] = permission.id.split(SitePermissions.PERM_KEY_DELIMITER); + + if (id == 'storage-access') { + // Ignore storage access permissions here, they are made visible inside + // the Content Blocking UI. + continue; + } + + let item = this.#createPermissionItem(id, key, permission); + if (item) { + list.appendChild(item); + } + } + + section.hidden = list.childElementCount == 0; + } + + #createPermissionItem(id, key, permission) {} + + handleEvent(event) { + const type = event.type; + switch (type) { + case 'command': + this.show(); + break; + } + } +} diff --git a/src/zen/urlbar/moz.build b/src/zen/urlbar/moz.build index 1e331db90..f321a86bb 100644 --- a/src/zen/urlbar/moz.build +++ b/src/zen/urlbar/moz.build @@ -3,6 +3,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. EXTRA_JS_MODULES += [ + "ZenSiteDataPanel.sys.mjs", "ZenUBActionsProvider.sys.mjs", "ZenUBGlobalActions.sys.mjs", "ZenUBProvider.sys.mjs",