--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -13,16 +13,20 @@ var Cr = Components.results;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/ContextualIdentityService.jsm");
Cu.import("resource://gre/modules/NotificationDB.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
"resource://gre/modules/Preferences.jsm");
+XPCOMUtils.defineLazyGetter(this, "extensionNameFromURI", () => {
+ return Cu.import("resource://gre/modules/ExtensionParent.jsm", {}).extensionNameFromURI;
+});
+
// lazy module getters
/* global AboutHome:false,
BrowserUITelemetry:false, BrowserUsageTelemetry:false, BrowserUtils:false,
CastingApps:false, CharsetMenu:false, Color:false, ContentSearch:false,
Deprecated:false, E10SUtils:false, ExtensionsUI: false, FormValidationHandler:false,
GMPInstallManager:false, LightweightThemeManager:false, Log:false,
LoginManagerParent:false, NewTabUtils:false, PageThumbs:false,
@@ -6875,16 +6879,21 @@ var gIdentityHandler = {
*
* These URIs, like "about:" and "data:" URIs, will usually be treated as a
* non-secure connection, unless they refer to an internally implemented
* browser page or resolve to "file:" URIs.
*/
_uriHasHost: false,
/**
+ * Whether this is a "moz-extension:" page, loaded from a WebExtension.
+ */
+ _isExtensionPage: false,
+
+ /**
* Whether this._uri refers to an internally implemented browser page.
*
* Note that this is set for some "about:" pages, but general "chrome:" URIs
* are not included in this category by default.
*/
_isSecureInternalUI: false,
/**
@@ -7008,16 +7017,20 @@ var gIdentityHandler = {
get _identityIconLabel() {
delete this._identityIconLabel;
return this._identityIconLabel = document.getElementById("identity-icon-label");
},
get _connectionIcon() {
delete this._connectionIcon;
return this._connectionIcon = document.getElementById("connection-icon");
},
+ get _extensionIcon() {
+ delete this._extensionIcon;
+ return this._extensionIcon = document.getElementById("extension-icon");
+ },
get _overrideService() {
delete this._overrideService;
return this._overrideService = Cc["@mozilla.org/security/certoverride;1"]
.getService(Ci.nsICertOverrideService);
},
get _identityIconCountryLabel() {
delete this._identityIconCountryLabel;
return this._identityIconCountryLabel = document.getElementById("identity-icon-country-label");
@@ -7286,17 +7299,21 @@ var gIdentityHandler = {
// swap the positions of the organization and country code labels.
// The Unicode ranges reflect the definition of the UCS2_CHAR_IS_BIDI
// macro in intl/unicharutil/util/nsBidiUtils.h. When bug 218823 gets
// fixed, this test should be replaced by one adhering to the
// Unicode Bidirectional Algorithm proper (at the paragraph level).
icon_labels_dir = /^[\u0590-\u08ff\ufb1d-\ufdff\ufe70-\ufefc]/.test(icon_label) ?
"rtl" : "ltr";
}
-
+ } else if (this._isExtensionPage) {
+ this._identityBox.className = "extensionPage";
+ let extensionName = extensionNameFromURI(this._uri);
+ icon_label = gNavigatorBundle.getFormattedString(
+ "identity.extension.label", [extensionName]);
} else if (this._uriHasHost && this._isSecure) {
this._identityBox.className = "verifiedDomain";
if (this._isMixedActiveContentBlocked) {
this._identityBox.classList.add("mixedActiveBlocked");
}
if (!this._isCertUserOverridden) {
// It's a normal cert, verifier is the CA Org.
tooltip = gNavigatorBundle.getFormattedString("identity.identified.verifier",
@@ -7354,16 +7371,23 @@ var gIdentityHandler = {
}
if (hasGrantedPermissions) {
this._identityBox.classList.add("grantedPermissions");
}
// Push the appropriate strings out to the UI
this._connectionIcon.tooltipText = tooltip;
+
+ if (this._isExtensionPage) {
+ let extensionName = extensionNameFromURI(this._uri);
+ this._extensionIcon.tooltipText = gNavigatorBundle.getFormattedString(
+ "identity.extension.tooltip", [extensionName]);
+ }
+
this._identityIconLabels.tooltipText = tooltip;
this._identityIcon.tooltipText = gNavigatorBundle.getString("identity.icon.tooltip");
this._identityIconLabel.value = icon_label;
this._identityIconCountryLabel.value = icon_country_label;
// Set cropping and direction
this._identityIconLabel.crop = icon_country_label ? "end" : "center";
this._identityIconLabel.parentNode.style.direction = icon_labels_dir;
// Hide completely if the organization label is empty
@@ -7385,16 +7409,18 @@ var gIdentityHandler = {
// The expander switches its tooltip when toggled, change it to the default.
this._popupExpander.tooltipText = gNavigatorBundle.getString("identity.showDetails.tooltip");
// Determine connection security information.
let connection = "not-secure";
if (this._isSecureInternalUI) {
connection = "chrome";
+ } else if (this._isExtensionPage) {
+ connection = "extension";
} else if (this._isURILoadedFromFile) {
connection = "file";
} else if (this._isEV) {
connection = "secure-ev";
} else if (this._isCertUserOverridden) {
connection = "secure-cert-user-overridden";
} else if (this._isSecure) {
connection = "secure";
@@ -7465,16 +7491,20 @@ var gIdentityHandler = {
// Fallback for special protocols.
if (!host) {
host = this._uri.specIgnoringRef;
// Special URIs without a host (eg, about:) should crop the end so
// the protocol can be seen.
hostless = true;
}
+ if (this._isExtensionPage) {
+ host = extensionNameFromURI(this._uri);
+ }
+
// Fill in the CA name if we have a valid TLS certificate.
if (this._isSecure || this._isCertUserOverridden) {
verifier = this._identityIconLabels.tooltipText;
}
// Fill in organization information if we have a valid EV certificate.
if (this._isEV) {
let iData = this.getIdentityData();
@@ -7518,16 +7548,18 @@ var gIdentityHandler = {
this._uriHasHost = true;
} catch (ex) {
this._uriHasHost = false;
}
let whitelist = /^(?:accounts|addons|cache|config|crashes|customizing|downloads|healthreport|home|license|newaddon|permissions|preferences|privatebrowsing|rights|searchreset|sessionrestore|support|welcomeback)(?:[?#]|$)/i;
this._isSecureInternalUI = uri.schemeIs("about") && whitelist.test(uri.path);
+ this._isExtensionPage = uri.schemeIs("moz-extension");
+
// Create a channel for the sole purpose of getting the resolved URI
// of the request to determine if it's loaded from the file system.
this._isURILoadedFromFile = false;
let chanOptions = {uri: this._uri, loadUsingSystemPrincipal: true};
let resolvedURI;
try {
resolvedURI = NetUtil.newChannel(chanOptions).URI;
if (resolvedURI.schemeIs("jar")) {
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -841,16 +841,17 @@
<image id="translated-notification-icon" class="notification-anchor-icon translation-icon in-use" role="button"
tooltiptext="&urlbar.translatedNotificationAnchor.tooltip;"/>
<image id="eme-notification-icon" class="notification-anchor-icon drm-icon" role="button"
tooltiptext="&urlbar.emeNotificationAnchor.tooltip;"/>
<image id="persistent-storage-notification-icon" class="notification-anchor-icon persistent-storage-icon" role="button"
tooltiptext="&urlbar.persistentStorageNotificationAnchor.tooltip;"/>
</box>
<image id="connection-icon"/>
+ <image id="extension-icon"/>
<image id="remote-control-icon"
tooltiptext="&urlbar.remoteControlNotificationAnchor.tooltip;"/>
<hbox id="identity-icon-labels">
<label id="identity-icon-label" class="plain" flex="1"/>
<label id="identity-icon-country-label" class="plain"/>
</hbox>
</box>
<box id="urlbar-display-box" align="center">
--- a/browser/components/controlcenter/content/panel.inc.xul
+++ b/browser/components/controlcenter/content/panel.inc.xul
@@ -27,16 +27,17 @@
<label class="identity-popup-headline identity-popup-hostless" crop="end"/>
</label>
<description class="identity-popup-connection-not-secure"
when-connection="not-secure secure-cert-user-overridden">&identity.connectionNotSecure;</description>
<description class="identity-popup-connection-secure"
when-connection="secure secure-ev">&identity.connectionSecure;</description>
<description when-connection="chrome">&identity.connectionInternal;</description>
<description when-connection="file">&identity.connectionFile;</description>
+ <description when-connection="extension">&identity.extensionPage;</description>
<vbox id="identity-popup-security-descriptions">
<description class="identity-popup-warning-gray"
when-mixedcontent="active-blocked">&identity.activeBlocked;</description>
<description class="identity-popup-warning-yellow"
when-mixedcontent="passive-loaded">&identity.passiveLoaded;</description>
<description when-mixedcontent="active-loaded">&identity.activeLoaded;</description>
<description class="identity-popup-warning-yellow"
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -61,16 +61,17 @@ support-files =
[browser_ext_currentWindow.js]
[browser_ext_devtools_inspectedWindow.js]
[browser_ext_devtools_inspectedWindow_reload.js]
[browser_ext_devtools_network.js]
[browser_ext_devtools_page.js]
[browser_ext_devtools_panel.js]
[browser_ext_geckoProfiler_symbolicate.js]
[browser_ext_getViews.js]
+[browser_ext_identity_indication.js]
[browser_ext_incognito_views.js]
[browser_ext_incognito_popup.js]
[browser_ext_lastError.js]
[browser_ext_omnibox.js]
skip-if = debug || asan # Bug 1354681
[browser_ext_optionsPage_browser_style.js]
[browser_ext_optionsPage_privileges.js]
[browser_ext_pageAction_context.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_identity_indication.js
@@ -0,0 +1,61 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+function confirmDefaults() {
+ let identityIconURL = getComputedStyle(document.getElementById("identity-icon")).listStyleImage;
+ is(identityIconURL, "url(\"chrome://browser/skin/identity-icon.svg#normal\")", "Identity icon should be the default identity icon");
+
+ let connectionIconURL = getComputedStyle(document.getElementById("connection-icon")).listStyleImage;
+ is(connectionIconURL, "none", "Connection icon should not be displayed");
+
+ let extensionIconURL = getComputedStyle(document.getElementById("extension-icon")).listStyleImage;
+ is(extensionIconURL, "none", "Extension icon should not be displayed");
+
+ let label = document.getElementById("identity-icon-label").value;
+ is(label, "", "No label should be used before the extension is started");
+}
+
+function confirmExtensionPage() {
+ let identityIcon = getComputedStyle(document.getElementById("identity-icon")).listStyleImage;
+ is(identityIcon, "url(\"chrome://browser/skin/identity-icon.svg#normal\")", "Identity icon should be the default identity icon");
+
+ let connectionIconURL = getComputedStyle(document.getElementById("connection-icon")).listStyleImage;
+ is(connectionIconURL, "none", "Connection icon should not be displayed");
+
+ let extensionIconEl = document.getElementById("extension-icon");
+ let extensionIconURL = getComputedStyle(extensionIconEl).listStyleImage;
+ is(extensionIconURL, "url(\"chrome://browser/skin/controlcenter/extension.svg\")", "Extension icon should be the default extension icon");
+ let tooltip = extensionIconEl.tooltipText;
+ is(tooltip, "Loaded by extension: Test Extension", "The correct tooltip should be used");
+
+ let label = document.getElementById("identity-icon-label").value;
+ is(label, "Extension (Test Extension)", "The correct label should be used");
+}
+
+add_task(async function testIdentityIndication() {
+ let extension = ExtensionTestUtils.loadExtension({
+ background() {
+ browser.test.sendMessage("url", browser.extension.getURL("icon.png"));
+ },
+ manifest: {
+ name: "Test Extension",
+ },
+ files: {
+ "icon.png": "",
+ },
+ });
+
+ await extension.startup();
+
+ confirmDefaults();
+
+ let url = await extension.awaitMessage("url");
+ await BrowserTestUtils.withNewTab({gBrowser, url}, async function() {
+ confirmExtensionPage();
+ });
+
+ await extension.unload();
+
+ confirmDefaults();
+});
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -714,16 +714,17 @@ you can use these alternative items. Oth
<!ENTITY editBookmark.done.label "Done">
<!ENTITY editBookmark.removeBookmark.accessKey "R">
<!ENTITY identity.connectionSecure "Secure Connection">
<!ENTITY identity.connectionNotSecure "Connection is Not Secure">
<!ENTITY identity.connectionFile "This page is stored on your computer.">
<!ENTITY identity.connectionVerified2 "You are securely connected to this site, owned by:">
<!ENTITY identity.connectionInternal "This is a secure &brandShortName; page.">
+<!ENTITY identity.extensionPage "This page is loaded from an extension.">
<!ENTITY identity.insecureLoginForms2 "Logins entered on this page could be compromised.">
<!-- Strings for connection state warnings. -->
<!ENTITY identity.activeBlocked "&brandShortName; has blocked parts of this page that are not secure.">
<!ENTITY identity.passiveLoaded "Parts of this page are not secure (such as images).">
<!ENTITY identity.activeLoaded "You have disabled protection on this page.">
<!ENTITY identity.weakEncryption "This page uses weak encryption.">
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -445,16 +445,18 @@ offlineApps.usage=This website (%S) is n
offlineApps.manageUsage=Show settings
offlineApps.manageUsageAccessKey=S
identity.identified.verifier=Verified by: %S
identity.identified.verified_by_you=You have added a security exception for this site.
identity.identified.state_and_country=%S, %S
identity.icon.tooltip=Show site information
+identity.extension.label=Extension (%S)
+identity.extension.tooltip=Loaded by extension: %S
identity.showDetails.tooltip=Show connection details
identity.hideDetails.tooltip=Hide connection details
trackingProtection.intro.title=How Tracking Protection works
# LOCALIZATION NOTE (trackingProtection.intro.description2):
# %S is brandShortName. This string should match the one from Step 1 of the tour
# when it starts from the button shown when a new private window is opened.
trackingProtection.intro.description2=When you see the shield, %S is blocking some parts of the page that could track your browsing activity.
copy from browser/components/extensions/extension.svg
copy to browser/themes/shared/controlcenter/extension.svg
--- a/browser/components/extensions/extension.svg
+++ b/browser/themes/shared/controlcenter/extension.svg
@@ -1,19 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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/. -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="64" height="64" viewBox="0 0 64 64">
- <defs>
- <style>
- .style-puzzle-piece {
- fill: url('#gradient-linear-puzzle-piece');
- }
- </style>
- <linearGradient id="gradient-linear-puzzle-piece" x1="0%" y1="0%" x2="0%" y2="100%">
- <stop offset="0%" stop-color="#66cc52" stop-opacity="1"/>
- <stop offset="100%" stop-color="#60bf4c" stop-opacity="1"/>
- </linearGradient>
- </defs>
- <path class="style-puzzle-piece" d="M42,62c2.2,0,4-1.8,4-4l0-14.2c0,0,0.4-3.7,2.8-3.7c2.4,0,2.2,3.9,6.7,3.9c2.3,0,6.2-1.2,6.2-8.2 c0-7-3.9-7.9-6.2-7.9c-4.5,0-4.3,3.7-6.7,3.7c-2.4,0-2.8-3.8-2.8-3.8V22c0-2.2-1.8-4-4-4H31.5c0,0-3.4-0.6-3.4-3 c0-2.4,3.8-2.6,3.8-7.1c0-2.3-1.3-5.9-8.3-5.9s-8,3.6-8,5.9c0,4.5,3.4,4.7,3.4,7.1c0,2.4-3.4,3-3.4,3H6c-2.2,0-4,1.8-4,4l0,7.8 c0,0-0.4,6,4.4,6c3.1,0,3.2-4.1,7.3-4.1c2,0,4,1.9,4,6c0,4.2-2,6.3-4,6.3c-4,0-4.2-4.1-7.3-4.1c-4.8,0-4.4,5.8-4.4,5.8L2,58 c0,2.2,1.8,4,4,4H19c0,0,6.3,0.4,6.3-4.4c0-3.1-4-3.6-4-7.7c0-2,2.2-4.5,6.4-4.5c4.2,0,6.6,2.5,6.6,4.5c0,4-3.9,4.6-3.9,7.7 c0,4.9,6.3,4.4,6.3,4.4H42z"/>
+#include ../icon-colors.inc.svg
+ <path class="fieldtext" d="M42,62c2.2,0,4-1.8,4-4l0-14.2c0,0,0.4-3.7,2.8-3.7c2.4,0,2.2,3.9,6.7,3.9c2.3,0,6.2-1.2,6.2-8.2 c0-7-3.9-7.9-6.2-7.9c-4.5,0-4.3,3.7-6.7,3.7c-2.4,0-2.8-3.8-2.8-3.8V22c0-2.2-1.8-4-4-4H31.5c0,0-3.4-0.6-3.4-3 c0-2.4,3.8-2.6,3.8-7.1c0-2.3-1.3-5.9-8.3-5.9s-8,3.6-8,5.9c0,4.5,3.4,4.7,3.4,7.1c0,2.4-3.4,3-3.4,3H6c-2.2,0-4,1.8-4,4l0,7.8 c0,0-0.4,6,4.4,6c3.1,0,3.2-4.1,7.3-4.1c2,0,4,1.9,4,6c0,4.2-2,6.3-4,6.3c-4,0-4.2-4.1-7.3-4.1c-4.8,0-4.4,5.8-4.4,5.8L2,58 c0,2.2,1.8,4,4,4H19c0,0,6.3,0.4,6.3-4.4c0-3.1-4-3.6-4-7.7c0-2,2.2-4.5,6.4-4.5c4.2,0,6.6,2.5,6.6,4.5c0,4-3.9,4.6-3.9,7.7 c0,4.9,6.3,4.4,6.3,4.4H42z"/>
</svg>
--- a/browser/themes/shared/controlcenter/panel.inc.css
+++ b/browser/themes/shared/controlcenter/panel.inc.css
@@ -11,16 +11,17 @@
/* Show the right elements for the right connection states. */
#identity-popup[connection=not-secure] [when-connection~=not-secure],
#identity-popup[connection=secure-cert-user-overridden] [when-connection~=secure-cert-user-overridden],
#identity-popup[connection=secure-ev] [when-connection~=secure-ev],
#identity-popup[connection=secure] [when-connection~=secure],
#identity-popup[connection=chrome] [when-connection~=chrome],
#identity-popup[connection=file] [when-connection~=file],
+#identity-popup[connection=extension] [when-connection~=extension],
/* Show insecure login forms messages when needed. */
#identity-popup[loginforms=insecure] [when-loginforms=insecure],
/* Show weak cipher messages when needed. */
#identity-popup[ciphers=weak] [when-ciphers~=weak],
/* Show mixed content warnings when needed */
#identity-popup[mixedcontent~=active-loaded] [when-mixedcontent=active-loaded],
#identity-popup[mixedcontent~=passive-loaded]:not([mixedcontent~=active-loaded]) [when-mixedcontent=passive-loaded],
#identity-popup[mixedcontent~=active-blocked]:not([mixedcontent~=passive-loaded]) [when-mixedcontent=active-blocked],
@@ -244,16 +245,21 @@
#identity-popup[loginforms=insecure] #identity-popup-securityView,
#identity-popup[loginforms=insecure] #identity-popup-security-content,
#identity-popup[mixedcontent~=active-loaded][isbroken] #identity-popup-securityView,
#identity-popup[mixedcontent~=active-loaded][isbroken] #identity-popup-security-content {
background-image: url(chrome://browser/skin/controlcenter/mcb-disabled.svg);
}
+#identity-popup[connection=extension] #identity-popup-securityView,
+#identity-popup[connection=extension] #identity-popup-security-content {
+ background-image: url(chrome://browser/skin/controlcenter/extension.svg);
+}
+
#identity-popup-security-descriptions > description {
margin-top: 6px;
color: Graytext;
}
#identity-popup-securityView-header,
#identity-popup-securityView-body {
margin-inline-start: calc(2em + 24px);
--- a/browser/themes/shared/identity-block/icons.inc.css
+++ b/browser/themes/shared/identity-block/icons.inc.css
@@ -8,16 +8,21 @@
list-style-image: url(chrome://browser/skin/identity-icon.svg#normal@iconVariant@);
}
#identity-box:hover > #identity-icon:not(.no-hover)@selectorSuffix@,
#identity-box[open=true] > #identity-icon@selectorSuffix@ {
list-style-image: url(chrome://browser/skin/identity-icon.svg#hover@iconVariant@);
}
+#identity-box.extensionPage > #extension-icon@selectorSuffix@ {
+ list-style-image: url(chrome://browser/skin/controlcenter/extension.svg);
+ visibility: visible;
+}
+
#identity-box.grantedPermissions > #identity-icon@selectorSuffix@ {
list-style-image: url(chrome://browser/skin/identity-icon.svg#notice@iconVariant@);
}
#identity-box.grantedPermissions:hover > #identity-icon:not(.no-hover)@selectorSuffix@,
#identity-box.grantedPermissions[open=true] > #identity-icon@selectorSuffix@ {
list-style-image: url(chrome://browser/skin/identity-icon.svg#notice-hover@iconVariant@);
}
--- a/browser/themes/shared/identity-block/identity-block.inc.css
+++ b/browser/themes/shared/identity-block/identity-block.inc.css
@@ -150,26 +150,25 @@
/* Only animate the shield in, when it disappears hide it immediately. */
transition: none;
}
#urlbar[pageproxystate="invalid"] > #identity-box > #tracking-protection-icon {
visibility: collapse;
}
-/* CONNECTION ICON */
+/* CONNECTION ICON, EXTENSION ICON */
-#connection-icon {
+#connection-icon, #extension-icon {
width: 16px;
height: 16px;
margin-inline-start: 2px;
visibility: collapse;
}
-
/* REMOTE CONTROL ICON */
#main-window[remotecontrol] #remote-control-icon {
list-style-image: url(chrome://browser/content/robot.ico);
visibility: visible;
width: 16px;
height: 16px;
margin-inline-start: 2px;
--- a/browser/themes/shared/jar.inc.mn
+++ b/browser/themes/shared/jar.inc.mn
@@ -23,16 +23,17 @@
skin/classic/browser/addons/addon-install-restart.svg (../shared/addons/addon-install-restart.svg)
skin/classic/browser/addons/addon-install-warning.svg (../shared/addons/addon-install-warning.svg)
* skin/classic/browser/addons/addon-install-anchor.svg (../shared/addons/addon-install-anchor.svg)
* skin/classic/browser/controlcenter/arrow-subview.svg (../shared/controlcenter/arrow-subview.svg)
* skin/classic/browser/controlcenter/arrow-subview-back.svg (../shared/controlcenter/arrow-subview-back.svg)
* skin/classic/browser/controlcenter/conn-not-secure.svg (../shared/controlcenter/conn-not-secure.svg)
* skin/classic/browser/controlcenter/connection.svg (../shared/controlcenter/connection.svg)
* skin/classic/browser/controlcenter/mcb-disabled.svg (../shared/controlcenter/mcb-disabled.svg)
+* skin/classic/browser/controlcenter/extension.svg (../shared/controlcenter/extension.svg)
* skin/classic/browser/controlcenter/permissions.svg (../shared/controlcenter/permissions.svg)
* skin/classic/browser/controlcenter/tracking-protection.svg (../shared/controlcenter/tracking-protection.svg)
skin/classic/browser/controlcenter/warning-gray.svg (../shared/controlcenter/warning-gray.svg)
skin/classic/browser/controlcenter/warning-yellow.svg (../shared/controlcenter/warning-yellow.svg)
skin/classic/browser/customizableui/customizeFavicon.ico (../shared/customizableui/customizeFavicon.ico)
skin/classic/browser/customizableui/customize-illustration.png (../shared/customizableui/customize-illustration.png)
skin/classic/browser/customizableui/customize-illustration@2x.png (../shared/customizableui/customize-illustration@2x.png)
skin/classic/browser/customizableui/customize-illustration-rtl.png (../shared/customizableui/customize-illustration-rtl.png)
--- a/toolkit/components/extensions/ExtensionParent.jsm
+++ b/toolkit/components/extensions/ExtensionParent.jsm
@@ -30,16 +30,20 @@ XPCOMUtils.defineLazyModuleGetter(this,
"resource://gre/modules/NativeMessaging.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Schemas",
"resource://gre/modules/Schemas.jsm");
+XPCOMUtils.defineLazyServiceGetter(this, "gAddonPolicyService",
+ "@mozilla.org/addons/policy-service;1",
+ "nsIAddonPolicyService");
+
Cu.import("resource://gre/modules/ExtensionCommon.jsm");
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
var {
BaseContext,
CanOfAPIs,
SchemaAPIManager,
} = ExtensionCommon;
@@ -891,17 +895,36 @@ function watchExtensionProxyContextLoad(
return () => {
extension.off("extension-proxy-context-load", listener);
};
}
// Used to cache the list of WebExtensionManifest properties defined in the BASE_SCHEMA.
let gBaseManifestProperties = null;
+/**
+ * Function to obtain the extension name from a moz-extension URI without exposing GlobalManager.
+ *
+ * @param {Object} uri The URI for the extension to look up.
+ * @returns {string} the name of the extension.
+ */
+function extensionNameFromURI(uri) {
+ let id = null;
+ try {
+ id = gAddonPolicyService.extensionURIToAddonId(uri);
+ } catch (ex) {
+ if (ex.name != "NS_ERROR_XPC_BAD_CONVERT_JS") {
+ Cu.reportError("Extension cannot be found in AddonPolicyService.");
+ }
+ }
+ return GlobalManager.getExtension(id).name;
+}
+
const ExtensionParent = {
+ extensionNameFromURI,
GlobalManager,
HiddenExtensionPage,
ParentAPIManager,
apiManager,
get baseManifestProperties() {
if (gBaseManifestProperties) {
return gBaseManifestProperties;
}