Revert "Issue #756 - Remove Contextual Identity from Basilisk"

This reverts commit ac50c95756.
This commit is contained in:
Roy Tam 2019-04-04 19:35:42 +08:00
commit a10f2e94ad
46 changed files with 1467 additions and 39 deletions

View file

@ -0,0 +1,176 @@
/* 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/. */
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/ContextualIdentityService.jsm");
const containersBundle = Services.strings.createBundle("chrome://browser/locale/preferences/containers.properties");
const HTMLNS = "http://www.w3.org/1999/xhtml";
let gContainersManager = {
icons: [
"fingerprint",
"briefcase",
"dollar",
"cart",
"circle"
],
colors: [
"blue",
"turquoise",
"green",
"yellow",
"orange",
"red",
"pink",
"purple"
],
onLoad() {
let params = window.arguments[0] || {};
this.init(params);
},
init(aParams) {
this.userContextId = aParams.userContextId || null;
this.identity = aParams.identity;
if (aParams.windowTitle) {
document.title = aParams.windowTitle;
}
const iconWrapper = document.getElementById("iconWrapper");
iconWrapper.appendChild(this.createIconButtons());
const colorWrapper = document.getElementById("colorWrapper");
colorWrapper.appendChild(this.createColorSwatches());
if (this.identity.name) {
const name = document.getElementById("name");
name.value = this.identity.name;
this.checkForm();
}
this.setLabelsMinWidth();
// This is to prevent layout jank caused by the svgs and outlines rendering at different times
document.getElementById("containers-content").removeAttribute("hidden");
},
setLabelsMinWidth() {
const labelMinWidth = containersBundle.GetStringFromName("containers.labelMinWidth");
const labels = [
document.getElementById("nameLabel"),
document.getElementById("iconLabel"),
document.getElementById("colorLabel")
];
for (let label of labels) {
label.style.minWidth = labelMinWidth;
}
},
uninit() {
},
// Check if name string as to if the form can be submitted
checkForm() {
const name = document.getElementById("name");
let btnApplyChanges = document.getElementById("btnApplyChanges");
if (!name.value) {
btnApplyChanges.setAttribute("disabled", true);
} else {
btnApplyChanges.removeAttribute("disabled");
}
},
createIconButtons(defaultIcon) {
let radiogroup = document.createElement("radiogroup");
radiogroup.setAttribute("id", "icon");
radiogroup.className = "icon-buttons";
for (let icon of this.icons) {
let iconSwatch = document.createElement("radio");
iconSwatch.id = "iconbutton-" + icon;
iconSwatch.name = "icon";
iconSwatch.type = "radio";
iconSwatch.value = icon;
if (this.identity.icon && this.identity.icon == icon) {
iconSwatch.setAttribute("selected", true);
}
iconSwatch.setAttribute("label",
containersBundle.GetStringFromName(`containers.${icon}.label`));
let iconElement = document.createElement("hbox");
iconElement.className = 'userContext-icon';
iconElement.setAttribute("data-identity-icon", icon);
iconSwatch.appendChild(iconElement);
radiogroup.appendChild(iconSwatch);
}
return radiogroup;
},
createColorSwatches(defaultColor) {
let radiogroup = document.createElement("radiogroup");
radiogroup.setAttribute("id", "color");
for (let color of this.colors) {
let colorSwatch = document.createElement("radio");
colorSwatch.id = "colorswatch-" + color;
colorSwatch.name = "color";
colorSwatch.type = "radio";
colorSwatch.value = color;
if (this.identity.color && this.identity.color == color) {
colorSwatch.setAttribute("selected", true);
}
colorSwatch.setAttribute("label",
containersBundle.GetStringFromName(`containers.${color}.label`));
let iconElement = document.createElement("hbox");
iconElement.className = 'userContext-icon';
iconElement.setAttribute("data-identity-icon", "circle");
iconElement.setAttribute("data-identity-color", color);
colorSwatch.appendChild(iconElement);
radiogroup.appendChild(colorSwatch);
}
return radiogroup;
},
onApplyChanges() {
let icon = document.getElementById("icon").value;
let color = document.getElementById("color").value;
let name = document.getElementById("name").value;
if (this.icons.indexOf(icon) == -1) {
throw "Internal error. The icon value doesn't match.";
}
if (this.colors.indexOf(color) == -1) {
throw "Internal error. The color value doesn't match.";
}
if (this.userContextId) {
ContextualIdentityService.update(this.userContextId,
name,
icon,
color);
} else {
ContextualIdentityService.create(name,
icon,
color);
}
window.parent.location.reload()
},
onWindowKeyPress(aEvent) {
if (aEvent.keyCode == KeyEvent.DOM_VK_ESCAPE)
window.close();
}
}

View file

@ -0,0 +1,52 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/containers.css" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://browser/locale/preferences/containers.dtd" >
<window id="ContainersDialog" class="windowDialog"
windowtype="Browser:Permissions"
title="&window.title;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
style="width: &window.width;;"
onload="gContainersManager.onLoad();"
onunload="gContainersManager.uninit();"
persist="screenX screenY width height"
onkeypress="gContainersManager.onWindowKeyPress(event);">
<script src="chrome://global/content/treeUtils.js"/>
<script src="chrome://browser/content/preferences/containers.js"/>
<stringbundle id="bundlePreferences"
src="chrome://browser/locale/preferences/preferences.properties"/>
<keyset>
<key key="&windowClose.key;" modifiers="accel" oncommand="window.close();"/>
</keyset>
<vbox class="contentPane largeDialogContainer" flex="1" hidden="true" id="containers-content">
<description id="permissionsText" control="url"/>
<separator class="thin"/>
<hbox align="start">
<label id="nameLabel" control="url" value="&name.label;" accesskey="&name.accesskey;"/>
<textbox id="name" flex="1" onkeyup="gContainersManager.checkForm();" />
</hbox>
<hbox align="center" id="iconWrapper">
<label id="iconLabel" control="url" value="&icon.label;" accesskey="&icon.accesskey;"/>
</hbox>
<hbox align="center" id="colorWrapper">
<label id="colorLabel" control="url" value="&color.label;" accesskey="&color.accesskey;"/>
</hbox>
</vbox>
<vbox>
<hbox class="actionButtons" align="right" flex="1">
<button id="btnApplyChanges" disabled="true" oncommand="gContainersManager.onApplyChanges();" icon="save"
label="&button.ok.label;" accesskey="&button.ok.accesskey;"/>
</hbox>
</vbox>
</window>

View file

@ -7,8 +7,12 @@ const nsICookie = Components.interfaces.nsICookie;
Components.utils.import("resource://gre/modules/AppConstants.jsm");
Components.utils.import("resource://gre/modules/PluralForm.jsm");
Components.utils.import("resource://gre/modules/Services.jsm")
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ContextualIdentityService",
"resource://gre/modules/ContextualIdentityService.jsm");
var gCookiesWindow = {
_cm : Components.classes["@mozilla.org/cookiemanager;1"]
.getService(Components.interfaces.nsICookieManager),
@ -34,6 +38,10 @@ var gCookiesWindow = {
this._populateList(true);
document.getElementById("filter").focus();
if (!Services.prefs.getBoolPref("privacy.userContext.enabled")) {
document.getElementById("userContextRow").hidden = true;
}
},
uninit: function () {
@ -74,11 +82,24 @@ var gCookiesWindow = {
aCookieB.originAttributes);
},
_isPrivateCookie: function (aCookie) {
let { userContextId } = aCookie.originAttributes;
if (!userContextId) {
// Default identity is public.
return false;
}
return !ContextualIdentityService.getIdentityFromId(userContextId).public;
},
observe: function (aCookie, aTopic, aData) {
if (aTopic != "cookie-changed")
return;
if (aCookie instanceof Components.interfaces.nsICookie) {
if (this._isPrivateCookie(aCookie)) {
return;
}
var strippedHost = this._makeStrippedHost(aCookie.host);
if (aData == "changed")
this._handleCookieChanged(aCookie, strippedHost);
@ -477,6 +498,9 @@ var gCookiesWindow = {
while (e.hasMoreElements()) {
var cookie = e.getNext();
if (cookie && cookie instanceof Components.interfaces.nsICookie) {
if (this._isPrivateCookie(cookie)) {
continue;
}
var strippedHost = this._makeStrippedHost(cookie.host);
this._addCookie(strippedHost, cookie, hostCount);
@ -500,9 +524,17 @@ var gCookiesWindow = {
return this._bundle.getString("expireAtEndOfSession");
},
_getUserContextString: function(aUserContextId) {
if (parseInt(aUserContextId) == 0) {
return this._bundle.getString("defaultUserContextLabel");
}
return ContextualIdentityService.getUserContextLabel(aUserContextId);
},
_updateCookieData: function (aItem) {
var seln = this._view.selection;
var ids = ["name", "value", "host", "path", "isSecure", "expires"];
var ids = ["name", "value", "host", "path", "isSecure", "expires", "userContext"];
var properties;
if (aItem && !aItem.container && seln.count > 0) {
@ -511,7 +543,8 @@ var gCookiesWindow = {
isDomain: aItem.isDomain ? this._bundle.getString("domainColon")
: this._bundle.getString("hostColon"),
isSecure: aItem.isSecure ? this._bundle.getString("forSecureOnly")
: this._bundle.getString("forAnyConnection") };
: this._bundle.getString("forAnyConnection"),
userContext: this._getUserContextString(aItem.originAttributes.userContextId) };
for (let id of ids) {
document.getElementById(id).disabled = false;
}
@ -520,7 +553,7 @@ var gCookiesWindow = {
var noneSelected = this._bundle.getString("noCookieSelected");
properties = { name: noneSelected, value: noneSelected, host: noneSelected,
path: noneSelected, expires: noneSelected,
isSecure: noneSelected };
isSecure: noneSelected, userContext: noneSelected };
for (let id of ids) {
document.getElementById(id).disabled = true;
}

View file

@ -85,6 +85,10 @@
<hbox pack="end"><label id="expiresLabel" control="expires" value="&props.expires.label;"/></hbox>
<textbox id="expires" readonly="true" class="plain"/>
</row>
<row align="center" id="userContextRow">
<hbox pack="end"><label id="userContextLabel" control="userContext" value="&props.container.label;"/></hbox>
<textbox id="userContext" readonly="true" class="plain"/>
</row>
</rows>
</grid>
</hbox>

View file

@ -10,6 +10,10 @@
-moz-binding: url("chrome://browser/content/preferences/handlers.xml#handler-selected");
}
#containersView > richlistitem {
-moz-binding: url("chrome://browser/content/preferences/handlers.xml#container");
}
/**
* Make the icons appear.
* Note: we display the icon box for every item whether or not it has an icon

View file

@ -69,6 +69,29 @@
</binding>
<binding id="container">
<content>
<xul:hbox flex="1" equalsize="always">
<xul:hbox flex="1" align="center">
<xul:hbox xbl:inherits="data-identity-icon=containerIcon,data-identity-color=containerColor" height="24" width="24" class="userContext-icon"/>
<xul:label flex="1" crop="end" xbl:inherits="value=containerName"/>
</xul:hbox>
<xul:hbox flex="1" align="right">
<xul:button anonid="preferencesButton"
xbl:inherits="value=userContextId"
onclick="gContainersPane.onPeferenceClick(event.originalTarget)">
Preferences
</xul:button>
<xul:button anonid="removeButton"
xbl:inherits="value=userContextId"
onclick="gContainersPane.onRemoveClick(event.originalTarget)">
Remove
</xul:button>
</xul:hbox>
</xul:hbox>
</content>
</binding>
<binding id="offlineapp"
extends="chrome://global/content/bindings/listbox.xml#listitem">
<content>

View file

@ -0,0 +1,73 @@
/* 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/. */
Components.utils.import("resource://gre/modules/AppConstants.jsm");
Components.utils.import("resource://gre/modules/ContextualIdentityService.jsm");
const containersBundle = Services.strings.createBundle("chrome://browser/locale/preferences/containers.properties");
const defaultContainerIcon = "fingerprint";
const defaultContainerColor = "blue";
let gContainersPane = {
init() {
this._list = document.getElementById("containersView");
document.getElementById("backContainersLink").addEventListener("click", function () {
gotoPref("privacy");
});
this._rebuildView();
},
_rebuildView() {
const containers = ContextualIdentityService.getIdentities();
while (this._list.firstChild) {
this._list.firstChild.remove();
}
for (let container of containers) {
let item = document.createElement("richlistitem");
item.setAttribute("containerName", ContextualIdentityService.getUserContextLabel(container.userContextId));
item.setAttribute("containerIcon", container.icon);
item.setAttribute("containerColor", container.color);
item.setAttribute("userContextId", container.userContextId);
this._list.appendChild(item);
}
},
onRemoveClick(button) {
let userContextId = button.getAttribute("value");
ContextualIdentityService.remove(userContextId);
this._rebuildView();
},
onPeferenceClick(button) {
this.openPreferenceDialog(button.getAttribute("value"));
},
onAddButtonClick(button) {
this.openPreferenceDialog(null);
},
openPreferenceDialog(userContextId) {
let identity = {
name: "",
icon: defaultContainerIcon,
color: defaultContainerColor
};
let title;
if (userContextId) {
identity = ContextualIdentityService.getIdentityFromId(userContextId);
// This is required to get the translation string from defaults
identity.name = ContextualIdentityService.getUserContextLabel(identity.userContextId);
title = containersBundle.formatStringFromName("containers.updateContainerTitle", [identity.name], 1);
}
const params = { userContextId, identity, windowTitle: title };
gSubDialog.open("chrome://browser/content/preferences/containers.xul",
null, params);
}
};

View file

@ -0,0 +1,54 @@
# 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/.
<!-- Containers panel -->
<script type="application/javascript"
src="chrome://browser/content/preferences/in-content/containers.js"/>
<preferences id="containerPreferences" hidden="true" data-category="paneContainer">
<!-- Containers -->
<preference id="privacy.userContext.enabled"
name="privacy.userContext.enabled"
type="bool"/>
</preferences>
<hbox hidden="true"
class="container-header-links"
data-category="paneContainers">
<label class="text-link" id="backContainersLink" value="&backLink.label;" />
</hbox>
<hbox id="header-containers"
class="header"
hidden="true"
data-category="paneContainers">
<label class="header-name" flex="1">&paneContainers.title;</label>
<button class="help-button"
aria-label="&helpButton.label;"/>
</hbox>
<!-- Containers -->
<groupbox id="browserContainersGroup" data-category="paneContainers" hidden="true">
<vbox id="browserContainersbox">
<richlistbox id="containersView" orient="vertical" persist="lastSelectedType"
flex="1">
<listheader equalsize="always">
<treecol id="typeColumn" label="&label.label;" value="type"
persist="sortDirection"
flex="1" sortDirection="ascending"/>
<treecol id="actionColumn" value="action"
persist="sortDirection"
flex="1"/>
</listheader>
</richlistbox>
</vbox>
<vbox>
<hbox flex="1">
<button onclick="gContainersPane.onAddButtonClick();" accesskey="&addButton.accesskey;" label="&addButton.label;"/>
</hbox>
</vbox>
</groupbox>

View file

@ -9,6 +9,7 @@ browser.jar:
content/browser/preferences/in-content/main.js
* content/browser/preferences/in-content/privacy.js
content/browser/preferences/in-content/containers.js
content/browser/preferences/in-content/advanced.js
content/browser/preferences/in-content/applications.js
* content/browser/preferences/in-content/content.js

View file

@ -61,6 +61,7 @@ function init_all() {
register_module("paneGeneral", gMainPane);
register_module("paneSearch", gSearchPane);
register_module("panePrivacy", gPrivacyPane);
register_module("paneContainers", gContainersPane);
register_module("paneAdvanced", gAdvancedPane);
register_module("paneApplications", gApplicationsPane);
register_module("paneContent", gContentPane);

View file

@ -13,6 +13,7 @@
href="chrome://browser/content/preferences/handlers.css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/applications.css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/in-content/search.css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/in-content/containers.css"?>
<!DOCTYPE page [
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
@ -26,6 +27,8 @@
<!ENTITY % syncDTD SYSTEM "chrome://browser/locale/preferences/sync.dtd">
<!ENTITY % securityDTD SYSTEM
"chrome://browser/locale/preferences/security.dtd">
<!ENTITY % containersDTD SYSTEM
"chrome://browser/locale/preferences/containers.dtd">
<!ENTITY % sanitizeDTD SYSTEM "chrome://browser/locale/sanitize.dtd">
<!ENTITY % mainDTD SYSTEM "chrome://browser/locale/preferences/main.dtd">
<!ENTITY % aboutHomeDTD SYSTEM "chrome://browser/locale/aboutHome.dtd">
@ -43,6 +46,7 @@
%syncBrandDTD;
%syncDTD;
%securityDTD;
%containersDTD;
%sanitizeDTD;
%mainDTD;
%aboutHomeDTD;
@ -130,6 +134,12 @@
<label class="category-name" flex="1">&panePrivacy.title;</label>
</richlistitem>
<richlistitem id="category-containers"
class="category"
value="paneContainers"
helpTopic="prefs-containers"
hidden="true"/>
<richlistitem id="category-security"
class="category"
value="paneSecurity"
@ -173,6 +183,7 @@
#include main.xul
#include search.xul
#include privacy.xul
#include containers.xul
#include advanced.xul
#include applications.xul
#include content.xul

View file

@ -5,6 +5,8 @@
Components.utils.import("resource://gre/modules/AppConstants.jsm");
Components.utils.import("resource://gre/modules/PluralForm.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ContextualIdentityService",
"resource://gre/modules/ContextualIdentityService.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
"resource://gre/modules/PluralForm.jsm");
@ -59,6 +61,59 @@ var gPrivacyPane = {
.getService(Components.interfaces.mozIPlacesAutoComplete);
},
/**
* Show the Containers UI depending on the privacy.userContext.ui.enabled pref.
*/
_initBrowserContainers: function () {
if (!Services.prefs.getBoolPref("privacy.userContext.ui.enabled")) {
return;
}
let link = document.getElementById("browserContainersLearnMore");
link.href = Services.urlFormatter.formatURLPref("app.support.baseURL") + "containers";
document.getElementById("browserContainersbox").hidden = false;
document.getElementById("browserContainersCheckbox").checked =
Services.prefs.getBoolPref("privacy.userContext.enabled");
},
_checkBrowserContainers: function(event) {
let checkbox = document.getElementById("browserContainersCheckbox");
if (checkbox.checked) {
Services.prefs.setBoolPref("privacy.userContext.enabled", true);
return;
}
let count = ContextualIdentityService.countContainerTabs();
if (count == 0) {
Services.prefs.setBoolPref("privacy.userContext.enabled", false);
return;
}
let bundlePreferences = document.getElementById("bundlePreferences");
let title = bundlePreferences.getString("disableContainersAlertTitle");
let message = PluralForm.get(count, bundlePreferences.getString("disableContainersMsg"))
.replace("#S", count)
let okButton = PluralForm.get(count, bundlePreferences.getString("disableContainersOkButton"))
.replace("#S", count)
let cancelButton = bundlePreferences.getString("disableContainersButton2");
let buttonFlags = (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_0) +
(Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_1);
let rv = Services.prompt.confirmEx(window, title, message, buttonFlags,
okButton, cancelButton, null, null, {});
if (rv == 0) {
ContextualIdentityService.closeAllContainerTabs();
Services.prefs.setBoolPref("privacy.userContext.enabled", false);
return;
}
checkbox.checked = true;
},
/**
* Sets up the UI for the number of days of history to keep, and updates the
* label of the "Clear Now..." button.
@ -81,6 +136,7 @@ var gPrivacyPane = {
this._initTrackingProtectionPBM();
#endif
this._initAutocomplete();
this._initBrowserContainers();
setEventListener("privacy.sanitize.sanitizeOnShutdown", "change",
gPrivacyPane._updateSanitizeSettingsButton);
@ -128,6 +184,10 @@ var gPrivacyPane = {
setEventListener("changeBlockListPBM", "command",
gPrivacyPane.showBlockLists);
#endif
setEventListener("browserContainersCheckbox", "command",
gPrivacyPane._checkBrowserContainers);
setEventListener("browserContainersSettings", "command",
gPrivacyPane.showContainerSettings);
},
#ifdef MOZ_SAFE_BROWSING
@ -429,6 +489,13 @@ var gPrivacyPane = {
},
#endif
/**
* Displays container panel for customising and adding containers.
*/
showContainerSettings() {
gotoPref("containers");
},
#ifdef MOZ_SAFE_BROWSING
/**
* Displays the available block lists for tracking protection.
@ -635,4 +702,25 @@ var gPrivacyPane = {
settingsButton.disabled = !sanitizeOnShutdownPref.value;
},
// CONTAINERS
/*
* preferences:
*
* privacy.userContext.enabled
* - true if containers is enabled
*/
/**
* Enables/disables the Settings button used to configure containers
*/
readBrowserContainersCheckbox: function ()
{
var pref = document.getElementById("privacy.userContext.enabled");
var settings = document.getElementById("browserContainersSettings");
settings.disabled = !pref.value;
}
};

View file

@ -302,3 +302,28 @@
&suggestionSettings.label;
</label>
</groupbox>
<!-- Containers -->
<groupbox id="browserContainersGroup" data-category="panePrivacy" hidden="true">
<vbox id="browserContainersbox" hidden="true">
<caption><label>&browserContainersHeader.label;
<label id="browserContainersLearnMore" class="text-link"
value="&browserContainersLearnMore.label;"/>
</label></caption>
<hbox align="start">
<vbox>
<checkbox id="browserContainersCheckbox"
label="&browserContainersEnabled.label;"
accesskey="&browserContainersEnabled.accesskey;"
preference="privacy.userContext.enabled"
onsyncfrompreference="return gPrivacyPane.readBrowserContainersCheckbox();"/>
</vbox>
<spacer flex="1"/>
<vbox>
<button id="browserContainersSettings"
label="&browserContainersSettings.label;"
accesskey="&browserContainersSettings.accesskey;"/>
</vbox>
</hbox>
</vbox>
</groupbox>

View file

@ -24,6 +24,8 @@ browser.jar:
* content/browser/preferences/languages.xul
content/browser/preferences/languages.js
content/browser/preferences/permissions.xul
content/browser/preferences/containers.xul
content/browser/preferences/containers.js
content/browser/preferences/permissions.js
content/browser/preferences/sanitize.xul
content/browser/preferences/sanitize.js