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

@ -51,11 +51,23 @@
label="&openLinkCmdInCurrent.label;"
accesskey="&openLinkCmdInCurrent.accesskey;"
oncommand="gContextMenu.openLinkInCurrent();"/>
# label is dynamically set.
# label and data-usercontextid are dynamically set.
<menuitem id="context-openlinkincontainertab"
accesskey="&openLinkCmdInTab.accesskey;"
oncommand="gContextMenu.openLinkInTab(event);"/>
<menuitem id="context-openlinkintab"
label="&openLinkCmdInTab.label;"
accesskey="&openLinkCmdInTab.accesskey;"
oncommand="gContextMenu.openLinkInTab();"/>
data-usercontextid="0"
oncommand="gContextMenu.openLinkInTab(event);"/>
<menu id="context-openlinkinusercontext-menu"
label="&openLinkCmdInContainerTab.label;"
accesskey="&openLinkCmdInContainerTab.accesskey;"
hidden="true">
<menupopup oncommand="gContextMenu.openLinkInTab(event);"
onpopupshowing="return gContextMenu.createContainerMenu(event);" />
</menu>
<menuitem id="context-openlink"
label="&openLinkCmd.label;"

View file

@ -11,12 +11,19 @@
style="border:0px;padding:0px;margin:0px;-moz-appearance:none">
<menu id="file-menu" label="&fileMenu.label;"
accesskey="&fileMenu.accesskey;">
<menupopup id="menu_FilePopup">
<menupopup id="menu_FilePopup"
onpopupshowing="updateUserContextUIVisibility();">
<menuitem id="menu_newNavigatorTab"
label="&tabCmd.label;"
command="cmd_newNavigatorTab"
key="key_newNavigatorTab"
accesskey="&tabCmd.accesskey;"/>
<menu id="menu_newUserContext"
label="&newUserContext.label;"
accesskey="&newUserContext.accesskey;"
hidden="true">
<menupopup onpopupshowing="return createUserContextMenu(event);" />
</menu>
<menuitem id="menu_newNavigator"
label="&newNavigatorCmd.label;"
accesskey="&newNavigatorCmd.accesskey;"

View file

@ -8,6 +8,7 @@ var Cu = Components.utils;
var Cc = Components.classes;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/ContextualIdentityService.jsm");
Cu.import("resource://gre/modules/NotificationDB.jsm");
// lazy module getters
@ -831,6 +832,10 @@ function _loadURIWithFlags(browser, uri, params) {
}
try {
if (!mustChangeProcess) {
if (params.userContextId) {
browser.webNavigation.setOriginAttributesBeforeLoading({ userContextId: params.userContextId });
}
browser.webNavigation.loadURIWithOptions(uri, flags,
referrer, referrerPolicy,
postData, null, null, triggeringPrincipal);
@ -856,6 +861,10 @@ function _loadURIWithFlags(browser, uri, params) {
postData: postData
}
if (params.userContextId) {
loadParams.userContextId = params.userContextId;
}
LoadInOtherProcess(browser, loadParams);
}
} catch (e) {
@ -868,6 +877,10 @@ function _loadURIWithFlags(browser, uri, params) {
Cu.reportError(e);
gBrowser.updateBrowserRemotenessByURL(browser, uri);
if (params.userContextId) {
browser.webNavigation.setOriginAttributesBeforeLoading({ userContextId: params.userContextId });
}
browser.webNavigation.loadURIWithOptions(uri, flags, referrer, referrerPolicy,
postData, null, null, triggeringPrincipal);
} else {
@ -931,6 +944,16 @@ addEventListener("DOMContentLoaded", function onDCL() {
let initBrowser =
document.getAnonymousElementByAttribute(gBrowser, "anonid", "initialBrowser");
// The window's first argument is a tab if and only if we are swapping tabs.
// We must set the browser's usercontextid before updateBrowserRemoteness(),
// so that the newly created remote tab child has the correct usercontextid.
if (window.arguments) {
let tabToOpen = window.arguments[0];
if (tabToOpen instanceof XULElement && tabToOpen.hasAttribute("usercontextid")) {
initBrowser.setAttribute("usercontextid", tabToOpen.getAttribute("usercontextid"));
}
}
gBrowser.updateBrowserRemoteness(initBrowser, gMultiProcessBrowser);
});
@ -1115,6 +1138,13 @@ var gBrowserInit = {
// make sure it has a docshell
gBrowser.docShell;
// We must set usercontextid before updateBrowserRemoteness()
// so that the newly created remote tab child has correct usercontextid
if (tabToOpen.hasAttribute("usercontextid")) {
let usercontextid = tabToOpen.getAttribute("usercontextid");
gBrowser.selectedBrowser.setAttribute("usercontextid", usercontextid);
}
// If the browser that we're swapping in was remote, then we'd better
// be able to support remote browsers, and then make our selectedTab
// remote.
@ -1140,8 +1170,9 @@ var gBrowserInit = {
// [3]: postData (nsIInputStream)
// [4]: allowThirdPartyFixup (bool)
// [5]: referrerPolicy (int)
// [6]: originPrincipal (nsIPrincipal)
// [7]: triggeringPrincipal (nsIPrincipal)
// [6]: userContextId (int)
// [7]: originPrincipal (nsIPrincipal)
// [8]: triggeringPrincipal (nsIPrincipal)
else if (window.arguments.length >= 3) {
let referrerURI = window.arguments[2];
if (typeof(referrerURI) == "string") {
@ -1153,11 +1184,13 @@ var gBrowserInit = {
}
let referrerPolicy = (window.arguments[5] != undefined ?
window.arguments[5] : Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT);
let userContextId = (window.arguments[6] != undefined ?
window.arguments[6] : Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID);
loadURI(uriToLoad, referrerURI, window.arguments[3] || null,
window.arguments[4] || false, referrerPolicy,
window.arguments[4] || false, referrerPolicy, userContextId,
// pass the origin principal (if any) and force its use to create
// an initial about:blank viewer if present:
window.arguments[6], !!window.arguments[6], window.arguments[7]);
window.arguments[7], !!window.arguments[7], window.arguments[8]);
window.focus();
}
// Note: loadOneOrMoreURIs *must not* be called if window.arguments.length >= 3.
@ -2042,7 +2075,7 @@ function BrowserTryToCloseWindow()
}
function loadURI(uri, referrer, postData, allowThirdPartyFixup, referrerPolicy,
originPrincipal, forceAboutBlankViewerInCurrent,
userContextId, originPrincipal, forceAboutBlankViewerInCurrent,
triggeringPrincipal) {
try {
openLinkIn(uri, "current",
@ -2050,6 +2083,7 @@ function loadURI(uri, referrer, postData, allowThirdPartyFixup, referrerPolicy,
referrerPolicy: referrerPolicy,
postData: postData,
allowThirdPartyFixup: allowThirdPartyFixup,
userContextId: userContextId,
originPrincipal,
triggeringPrincipal,
forceAboutBlankViewerInCurrent,
@ -3923,6 +3957,66 @@ function updateEditUIVisibility()
}
}
/**
* Opens a new tab with the userContextId specified as an attribute of
* sourceEvent. This attribute is propagated to the top level originAttributes
* living on the tab's docShell.
*
* @param event
* A click event on a userContext File Menu option
*/
function openNewUserContextTab(event)
{
openUILinkIn(BROWSER_NEW_TAB_URL, "tab", {
userContextId: parseInt(event.target.getAttribute('data-usercontextid')),
});
}
/**
* Updates File Menu User Context UI visibility depending on
* privacy.userContext.enabled pref state.
*/
function updateUserContextUIVisibility()
{
let menu = document.getElementById("menu_newUserContext");
menu.hidden = !Services.prefs.getBoolPref("privacy.userContext.enabled");
if (PrivateBrowsingUtils.isWindowPrivate(window)) {
menu.setAttribute("disabled", "true");
}
}
/**
* Updates the User Context UI indicators if the browser is in a non-default context
*/
function updateUserContextUIIndicator()
{
let hbox = document.getElementById("userContext-icons");
let userContextId = gBrowser.selectedBrowser.getAttribute("usercontextid");
if (!userContextId) {
hbox.setAttribute("data-identity-color", "");
hbox.hidden = true;
return;
}
let identity = ContextualIdentityService.getIdentityFromId(userContextId);
if (!identity) {
hbox.setAttribute("data-identity-color", "");
hbox.hidden = true;
return;
}
hbox.setAttribute("data-identity-color", identity.color);
let label = document.getElementById("userContext-label");
label.setAttribute("value", ContextualIdentityService.getUserContextLabel(userContextId));
let indicator = document.getElementById("userContext-indicator");
indicator.setAttribute("data-identity-icon", identity.icon);
hbox.hidden = false;
}
/**
* Makes the Character Encoding menu enabled or disabled as appropriate.
* To be called when the View menu or the app menu is opened.
@ -4603,6 +4697,7 @@ nsBrowserAccess.prototype = {
_openURIInNewTab: function(aURI, aReferrer, aReferrerPolicy, aIsPrivate,
aIsExternal, aForceNotRemote=false,
aUserContextId=Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID,
aOpener = null, aTriggeringPrincipal = null) {
let win, needToFocusWin;
@ -4631,6 +4726,7 @@ nsBrowserAccess.prototype = {
triggeringPrincipal: aTriggeringPrincipal,
referrerURI: aReferrer,
referrerPolicy: aReferrerPolicy,
userContextId: aUserContextId,
fromExternal: aIsExternal,
inBackground: loadInBackground,
forceNotRemote: aForceNotRemote,
@ -4707,10 +4803,13 @@ nsBrowserAccess.prototype = {
// will do the job of shuttling off the newly opened browser to run in
// the right process once it starts loading a URI.
let forceNotRemote = !!aOpener;
let userContextId = aOpener && aOpener.document
? aOpener.document.nodePrincipal.originAttributes.userContextId
: Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID;
let openerWindow = (aFlags & Ci.nsIBrowserDOMWindow.OPEN_NO_OPENER) ? null : aOpener;
let browser = this._openURIInNewTab(aURI, referrer, referrerPolicy,
isPrivate, isExternal,
forceNotRemote,
forceNotRemote, userContextId,
openerWindow, triggeringPrincipal);
if (browser)
newWindow = browser.contentWindow;
@ -4742,10 +4841,16 @@ nsBrowserAccess.prototype = {
var isExternal = !!(aFlags & Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
var userContextId = aParams.openerOriginAttributes &&
("userContextId" in aParams.openerOriginAttributes)
? aParams.openerOriginAttributes.userContextId
: Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID
let browser = this._openURIInNewTab(aURI, aParams.referrer,
aParams.referrerPolicy,
aParams.isPrivate,
isExternal, false,
userContextId, null,
aParams.triggeringPrincipal);
if (browser)
return browser.QueryInterface(Ci.nsIFrameLoaderOwner);
@ -5303,6 +5408,11 @@ function handleLinkClick(event, href, linkNode) {
triggeringPrincipal: doc.nodePrincipal,
};
// The new tab/window must use the same userContextId
if (doc.nodePrincipal.originAttributes.userContextId) {
params.userContextId = doc.nodePrincipal.originAttributes.userContextId;
}
openLinkIn(href, where, params);
event.preventDefault();
return true;
@ -5374,6 +5484,8 @@ function handleDroppedLink(event, urlOrLinks, name)
let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange;
let userContextId = gBrowser.selectedBrowser.getAttribute("usercontextid");
// event is null if links are dropped in content process.
// inBackground should be false, as it's loading into current browser.
let inBackground = false;
@ -5397,6 +5509,7 @@ function handleDroppedLink(event, urlOrLinks, name)
replace: true,
allowThirdPartyFixup: false,
postDatas,
userContextId,
});
}
});

View file

@ -8,6 +8,7 @@
<?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/places/places.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/usercontext/usercontext.css" type="text/css"?>
#ifdef MOZ_DEVTOOLS
<?xml-stylesheet href="chrome://devtools/skin/devtools-browser.css" type="text/css"?>
#endif
@ -552,7 +553,12 @@
key="key_undoCloseTab"
label="&undoCloseTab.label;"
observes="History:UndoCloseTab"/>
<menuseparator id="alltabs-popup-separator"/>
<menuseparator id="alltabs-popup-separator-1"/>
<menu id="alltabs_containersTab"
label="&newUserContext.label;">
<menupopup id="alltabs_containersMenuTab" />
</menu>
<menuseparator id="alltabs-popup-separator-2"/>
</menupopup>
</toolbarbutton>

View file

@ -162,6 +162,9 @@ var handleContentContextMenu = function (event) {
let selectionInfo = BrowserUtils.getSelectionDetails(content);
let loadContext = docShell.QueryInterface(Ci.nsILoadContext);
let userContextId = loadContext.originAttributes.userContextId;
if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
let editFlags = SpellCheckHelper.isEditable(event.target, content);
let spellInfo;
@ -185,7 +188,7 @@ var handleContentContextMenu = function (event) {
principal, docLocation, charSet, baseURI, referrer,
referrerPolicy, contentType, contentDisposition,
frameOuterWindowID, selectionInfo, disableSetDesktopBg,
loginFillInfo, parentAllowsMixedContent },
loginFillInfo, parentAllowsMixedContent, userContextId },
{ event, popupNode: event.target });
}
else {
@ -209,6 +212,7 @@ var handleContentContextMenu = function (event) {
disableSetDesktopBackground: disableSetDesktopBg,
loginFillInfo,
parentAllowsMixedContent,
userContextId,
};
}
}

View file

@ -4,6 +4,7 @@
# 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/ContextualIdentityService.jsm");
Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
Components.utils.import("resource://gre/modules/InlineSpellChecker.jsm");
Components.utils.import("resource://gre/modules/LoginManagerContextMenu.jsm");
@ -141,11 +142,28 @@ nsContextMenu.prototype = {
this.onPlainTextLink = true;
}
var inContainer = false;
if (gContextMenuContentData.userContextId) {
inContainer = true;
var item = document.getElementById("context-openlinkincontainertab");
item.setAttribute("data-usercontextid", gContextMenuContentData.userContextId);
var label =
ContextualIdentityService.getUserContextLabel(gContextMenuContentData.userContextId);
item.setAttribute("label",
gBrowserBundle.formatStringFromName("userContextOpenLink.label",
[label], 1));
}
var shouldShow = this.onSaveableLink || isMailtoInternal || this.onPlainTextLink;
var isWindowPrivate = PrivateBrowsingUtils.isWindowPrivate(window);
var showContainers = Services.prefs.getBoolPref("privacy.userContext.enabled");
this.showItem("context-openlink", shouldShow && !isWindowPrivate);
this.showItem("context-openlinkprivate", shouldShow);
this.showItem("context-openlinkintab", shouldShow);
this.showItem("context-openlinkintab", shouldShow && !inContainer);
this.showItem("context-openlinkincontainertab", shouldShow && inContainer);
this.showItem("context-openlinkinusercontext-menu", shouldShow && !isWindowPrivate && showContainers);
this.showItem("context-openlinkincurrent", this.onPlainTextLink);
this.showItem("context-sep-open", shouldShow);
},
@ -940,6 +958,13 @@ nsContextMenu.prototype = {
params[p] = extra[p];
}
// If we want to change userContextId, we must be sure that we don't
// propagate the referrer.
if ("userContextId" in params &&
params.userContextId != gContextMenuContentData.userContextId) {
params.noReferrer = true;
}
return params;
},
@ -957,7 +982,7 @@ nsContextMenu.prototype = {
},
// Open linked-to URL in a new tab.
openLinkInTab: function() {
openLinkInTab: function(event) {
urlSecurityCheck(this.linkURL, this.principal);
let referrerURI = gContextMenuContentData.documentURIObject;
@ -978,6 +1003,7 @@ nsContextMenu.prototype = {
let params = {
allowMixedContent: persistAllowMixedContentInChildTab,
userContextId: parseInt(event.target.getAttribute('data-usercontextid')),
};
openLinkIn(this.linkURL, "tab", this._openLinkInParameters(params));
@ -1753,4 +1779,8 @@ nsContextMenu.prototype = {
menuItem.label = menuLabel;
menuItem.accessKey = gNavigatorBundle.getString("contextMenuSearch.accesskey");
},
createContainerMenu: function(aEvent) {
return createUserContextMenu(aEvent, true,
gContextMenuContentData.userContextId);
},
};

View file

@ -889,6 +889,33 @@ var RefreshBlocker = {
RefreshBlocker.init();
var UserContextIdNotifier = {
init() {
addEventListener("DOMWindowCreated", this);
},
uninit() {
removeEventListener("DOMWindowCreated", this);
},
handleEvent(aEvent) {
// When the window is created, we want to inform the tabbrowser about
// the userContextId in use in order to update the UI correctly.
// Just because we cannot change the userContextId from an active docShell,
// we don't need to check DOMContentLoaded again.
this.uninit();
// We use the docShell because content.document can have been loaded before
// setting the originAttributes.
let loadContext = docShell.QueryInterface(Ci.nsILoadContext);
let userContextId = loadContext.originAttributes.userContextId;
sendAsyncMessage("Browser:WindowCreated", { userContextId });
}
};
UserContextIdNotifier.init();
#ifdef MOZ_WEBEXTENSIONS
ExtensionContent.init(this);
addEventListener("unload", () => {

View file

@ -826,8 +826,10 @@
}
let unifiedComplete = this.mTabBrowser._unifiedComplete;
let userContextId = this.mBrowser.getAttribute("usercontextid") || 0;
if (this.mBrowser.registeredOpenURI) {
unifiedComplete.unregisterOpenPage(this.mBrowser.registeredOpenURI);
unifiedComplete.unregisterOpenPage(this.mBrowser.registeredOpenURI,
userContextId);
delete this.mBrowser.registeredOpenURI;
}
// Tabs in private windows aren't registered as "Open" so
@ -835,7 +837,7 @@
if (!isBlankPageURL(aLocation.spec) &&
(!PrivateBrowsingUtils.isWindowPrivate(window) ||
PrivateBrowsingUtils.permanentPrivateBrowsing)) {
unifiedComplete.registerOpenPage(aLocation);
unifiedComplete.registerOpenPage(aLocation, userContextId);
this.mBrowser.registeredOpenURI = aLocation;
}
}
@ -1240,6 +1242,7 @@
this._adjustFocusAfterTabSwitch(this.mCurrentTab);
}
updateUserContextUIIndicator();
gIdentityHandler.updateSharingIndicator();
this.tabContainer._setPositionalAttributes();
@ -1495,6 +1498,7 @@
var aSkipAnimation;
var aForceNotRemote;
var aNoReferrer;
var aUserContextId;
var aRelatedBrowser;
var aOriginPrincipal;
var aOpener;
@ -1515,6 +1519,7 @@
aSkipAnimation = params.skipAnimation;
aForceNotRemote = params.forceNotRemote;
aNoReferrer = params.noReferrer;
aUserContextId = params.userContextId;
aRelatedBrowser = params.relatedBrowser;
aOriginPrincipal = params.originPrincipal;
aOpener = params.opener;
@ -1537,6 +1542,7 @@
allowMixedContent: aAllowMixedContent,
forceNotRemote: aForceNotRemote,
noReferrer: aNoReferrer,
userContextId: aUserContextId,
originPrincipal: aOriginPrincipal,
relatedBrowser: aRelatedBrowser,
opener: aOpener });
@ -1557,6 +1563,7 @@
let aTargetTab;
let aNewIndex = -1;
let aPostDatas = [];
let aUserContextId;
if (arguments.length == 2 &&
typeof arguments[1] == "object") {
let params = arguments[1];
@ -1567,6 +1574,7 @@
aNewIndex = typeof params.newIndex === "number" ?
params.newIndex : aNewIndex;
aPostDatas = params.postDatas || aPostDatas;
aUserContextId = params.userContextId;
}
if (!aURIs.length)
@ -1615,7 +1623,8 @@
ownerTab: owner,
skipAnimation: multiple,
allowThirdPartyFixup: aAllowThirdPartyFixup,
postData: aPostDatas[0]
postData: aPostDatas[0],
userContextId: aUserContextId
});
if (aNewIndex !== -1) {
this.moveTabTo(firstTabAdded, aNewIndex);
@ -1628,7 +1637,8 @@
let tab = this.addTab(aURIs[i], {
skipAnimation: true,
allowThirdPartyFixup: aAllowThirdPartyFixup,
postData: aPostDatas[i]
postData: aPostDatas[i],
userContextId: aUserContextId
});
if (targetTabIndex !== -1)
this.moveTabTo(tab, ++tabNum);
@ -1901,7 +1911,7 @@
<body>
<![CDATA[
// Supported parameters:
// remote, isPreloadBrowser, uriIsAboutBlank, permanentKey
// userContextId, remote, isPreloadBrowser, uriIsAboutBlank, permanentKey
const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
@ -1913,6 +1923,10 @@
b.setAttribute("contextmenu", this.getAttribute("contentcontextmenu"));
b.setAttribute("tooltip", this.getAttribute("contenttooltip"));
if (aParams.userContextId) {
b.setAttribute("usercontextid", aParams.userContextId);
}
if (aParams.remote) {
b.setAttribute("remote", "true");
}
@ -1995,7 +2009,7 @@
"use strict";
// Supported parameters:
// forceNotRemote
// forceNotRemote, userContextId
let uriIsAboutBlank = !aURI || aURI == "about:blank";
@ -2013,6 +2027,7 @@
// Private windows are not included because both the label and the
// icon for the tab would be set incorrectly (see bug 1195981).
if (aURI == BROWSER_NEW_TAB_URL &&
!aParams.userContextId &&
!PrivateBrowsingUtils.isWindowPrivate(window)) {
browser = this._getPreloadedBrowser();
if (browser) {
@ -2026,6 +2041,7 @@
browser = this._createBrowser({permanentKey: aTab.permanentKey,
remote: remote,
uriIsAboutBlank: uriIsAboutBlank,
userContextId: aParams.userContextId,
relatedBrowser: aParams.relatedBrowser,
opener: aParams.opener});
}
@ -2100,6 +2116,7 @@
var aAllowMixedContent;
var aForceNotRemote;
var aNoReferrer;
var aUserContextId;
var aEventDetail;
var aRelatedBrowser;
var aOriginPrincipal;
@ -2122,6 +2139,7 @@
aAllowMixedContent = params.allowMixedContent;
aForceNotRemote = params.forceNotRemote;
aNoReferrer = params.noReferrer;
aUserContextId = params.userContextId;
aEventDetail = params.eventDetail;
aRelatedBrowser = params.relatedBrowser;
aOriginPrincipal = params.originPrincipal;
@ -2148,6 +2166,11 @@
t.setAttribute("label", aURI);
}
if (aUserContextId) {
t.setAttribute("usercontextid", aUserContextId);
ContextualIdentityService.setTabStyle(t);
}
t.setAttribute("crop", "end");
t.setAttribute("onerror", "this.removeAttribute('image');");
@ -2197,6 +2220,7 @@
// of tab.linkedBrowser.
let browserParams = {
forceNotRemote: aForceNotRemote,
userContextId: aUserContextId,
relatedBrowser: aRelatedBrowser,
opener: aOpener,
};
@ -2575,7 +2599,8 @@
listener.destroy();
if (browser.registeredOpenURI && !aAdoptedByTab) {
this._unifiedComplete.unregisterOpenPage(browser.registeredOpenURI);
this._unifiedComplete.unregisterOpenPage(browser.registeredOpenURI,
browser.getAttribute("usercontextid") || 0);
delete browser.registeredOpenURI;
}
@ -2774,6 +2799,11 @@
if (ourBrowser.isRemoteBrowser != otherBrowser.isRemoteBrowser)
return;
// Keep the userContextId if set on other browser
if (otherBrowser.hasAttribute("usercontextid")) {
ourBrowser.setAttribute("usercontextid", otherBrowser.getAttribute("usercontextid"));
}
// That's gBrowser for the other window, not the tab's browser!
var remoteBrowser = aOtherTab.ownerDocument.defaultView.gBrowser;
var isPending = aOtherTab.hasAttribute("pending");
@ -2806,6 +2836,10 @@
aOurTab.setAttribute("soundplaying", "true");
modifiedAttrs.push("soundplaying");
}
if (aOtherTab.hasAttribute("usercontextid")) {
aOurTab.setUserContextId(aOtherTab.getAttribute("usercontextid"));
modifiedAttrs.push("usercontextid");
}
if (aOtherTab.hasAttribute("sharing")) {
aOurTab.setAttribute("sharing", aOtherTab.getAttribute("sharing"));
modifiedAttrs.push("sharing");
@ -2943,7 +2977,8 @@
<![CDATA[
// If the current URI is registered as open remove it from the list.
if (aOurBrowser.registeredOpenURI) {
this._unifiedComplete.unregisterOpenPage(aOurBrowser.registeredOpenURI);
this._unifiedComplete.unregisterOpenPage(aOurBrowser.registeredOpenURI,
aOurBrowser.getAttribute("usercontextid") || 0);
delete aOurBrowser.registeredOpenURI;
}
@ -3283,6 +3318,10 @@
// it in the other window (making it seem to have moved between
// windows).
let params = { eventDetail: { adoptedTab: aTab } };
if (aTab.hasAttribute("usercontextid")) {
// new tab must have the same usercontextid as the old one
params.userContextId = aTab.getAttribute("usercontextid");
}
let newTab = this.addTab("about:blank", params);
let newBrowser = this.getBrowserForTab(newTab);
let newURL = aTab.linkedBrowser.currentURI.spec;
@ -4602,6 +4641,7 @@
disableSetDesktopBackground: data.disableSetDesktopBg,
loginFillInfo: data.loginFillInfo,
parentAllowsMixedContent: data.parentAllowsMixedContent,
userContextId: data.userContextId,
};
let popup = browser.ownerDocument.getElementById("contentAreaContextMenu");
let event = gContextMenuContentData.event;
@ -4628,6 +4668,17 @@
}
case "Browser:WindowCreated": {
let tab = this.getTabForBrowser(browser);
if (tab && data.userContextId) {
ContextualIdentityService.telemetry(data.userContextId);
tab.setUserContextId(data.userContextId);
}
// We don't want to update the container icon and identifier if
// this is not the selected browser.
if (browser == gBrowser.selectedBrowser) {
updateUserContextUIIndicator();
}
break;
}
case "Findbar:Keypress": {
@ -4811,7 +4862,8 @@
for (let tab of this.tabs) {
let browser = tab.linkedBrowser;
if (browser.registeredOpenURI) {
this._unifiedComplete.unregisterOpenPage(browser.registeredOpenURI);
this._unifiedComplete.unregisterOpenPage(browser.registeredOpenURI,
browser.getAttribute("usercontextid") || 0);
delete browser.registeredOpenURI;
}
let filter = this._tabFilters.get(tab);
@ -5212,7 +5264,7 @@
</xul:arrowscrollbox>
</content>
<implementation implements="nsIDOMEventListener">
<implementation implements="nsIDOMEventListener, nsIObserver">
<constructor>
<![CDATA[
this.mTabClipWidth = Services.prefs.getIntPref("browser.tabs.tabClipWidth");
@ -5231,9 +5283,17 @@
this._tabAnimationLoggingEnabled = false;
}
this._browserNewtabpageEnabled = Services.prefs.getBoolPref("browser.newtabpage.enabled");
this.observe(null, "nsPref:changed", "privacy.userContext.enabled");
Services.prefs.addObserver("privacy.userContext.enabled", this, false);
]]>
</constructor>
<destructor>
<![CDATA[
Services.prefs.removeObserver("privacy.userContext.enabled", this);
]]>
</destructor>
<field name="tabbrowser" readonly="true">
document.getElementById(this.getAttribute("tabbrowser"));
</field>
@ -5259,6 +5319,55 @@
<field name="_afterHoveredTab">null</field>
<field name="_hoveredTab">null</field>
<method name="observe">
<parameter name="aSubject"/>
<parameter name="aTopic"/>
<parameter name="aData"/>
<body><![CDATA[
switch (aTopic) {
case "nsPref:changed":
// This is the only pref observed.
let containersEnabled = Services.prefs.getBoolPref("privacy.userContext.enabled");
const newTab = document.getElementById("new-tab-button");
const newTab2 = document.getAnonymousElementByAttribute(this, "anonid", "tabs-newtab-button")
if (containersEnabled) {
for (let parent of [newTab, newTab2]) {
if (!parent)
continue;
let popup = document.createElementNS(
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
"menupopup");
if (parent.id) {
popup.id = "newtab-popup";
} else {
popup.setAttribute("anonid", "newtab-popup");
}
popup.className = "new-tab-popup";
popup.setAttribute("position", "after_end");
parent.appendChild(popup);
gClickAndHoldListenersOnElement.add(parent);
parent.setAttribute("type", "menu");
}
} else {
for (let parent of [newTab, newTab2]) {
if (!parent)
continue;
gClickAndHoldListenersOnElement.remove(parent);
parent.removeAttribute("type");
if (!parent.firstChild)
continue;
parent.firstChild.remove();
}
}
break;
}
]]></body>
</method>
<property name="_isCustomizing" readonly="true">
<getter>
let root = document.documentElement;
@ -6361,6 +6470,7 @@
inBackground = !inBackground;
let targetTab = this._getDragTargetTab(event, true);
let userContextId = this.selectedItem.getAttribute("usercontextid");
let replace = !!targetTab;
let newIndex = this._getDropIndex(event, true);
let urls = links.map(link => link.url);
@ -6370,6 +6480,7 @@
allowThirdPartyFixup: true,
targetTab,
newIndex,
userContextId,
});
}
@ -6630,6 +6741,14 @@
-->
<field name="muteReason">undefined</field>
<property name="userContextId" readonly="true">
<getter>
return this.hasAttribute("usercontextid")
? parseInt(this.getAttribute("usercontextid"))
: 0;
</getter>
</property>
<property name="soundPlaying" readonly="true">
<getter>
return this.getAttribute("soundplaying") == "true";
@ -6757,6 +6876,27 @@
]]>
</body>
</method>
<method name="setUserContextId">
<parameter name="aUserContextId"/>
<body>
<![CDATA[
if (aUserContextId) {
if (this.linkedBrowser) {
this.linkedBrowser.setAttribute("usercontextid", aUserContextId);
}
this.setAttribute("usercontextid", aUserContextId);
} else {
if (this.linkedBrowser) {
this.linkedBrowser.removeAttribute("usercontextid");
}
this.removeAttribute("usercontextid");
}
ContextualIdentityService.setTabStyle(this);
]]>
</body>
</method>
</implementation>
<handlers>
@ -6933,9 +7073,30 @@
<handlers>
<handler event="popupshowing">
<![CDATA[
if (event.target.getAttribute("id") == "alltabs_containersMenuTab") {
createUserContextMenu(event);
return;
}
let containersEnabled = Services.prefs.getBoolPref("privacy.userContext.enabled");
if (event.target.getAttribute("anonid") == "newtab-popup" ||
event.target.id == "newtab-popup") {
createUserContextMenu(event);
} else {
document.getElementById("alltabs-popup-separator-1").hidden = !containersEnabled;
let containersTab = document.getElementById("alltabs_containersTab");
containersTab.hidden = !containersEnabled;
if (PrivateBrowsingUtils.isWindowPrivate(window)) {
containersTab.setAttribute("disabled", "true");
}
document.getElementById("alltabs_undoCloseTab").disabled =
SessionStore.getClosedTabCount(window) == 0;
var tabcontainer = gBrowser.tabContainer;
// Listen for changes in the tab bar.
tabcontainer.addEventListener("TabAttrModified", this, false);
tabcontainer.addEventListener("TabClose", this, false);
@ -6952,6 +7113,9 @@
<handler event="popuphidden">
<![CDATA[
if (event.target.getAttribute("id") == "alltabs_containersMenuTab") {
return;
}
// clear out the menu popup and remove the listeners
for (let i = this.childNodes.length - 1; i > 0; i--) {
@ -6960,6 +7124,9 @@
menuItem.tab.mCorrespondingMenuitem = null;
this.removeChild(menuItem);
}
if (menuItem.hasAttribute("usercontextid")) {
this.removeChild(menuItem);
}
}
var tabcontainer = gBrowser.tabContainer;
tabcontainer.mTabstrip.removeEventListener("scroll", this, false);

View file

@ -5,6 +5,7 @@
// Services = object with smart getters for common XPCOM services
Components.utils.import("resource://gre/modules/AppConstants.jsm");
Components.utils.import("resource://gre/modules/ContextualIdentityService.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
@ -175,6 +176,7 @@ function whereToOpenLink( e, ignoreButton, ignoreAlt )
* skipTabAnimation (boolean)
* allowPinnedTabHostChange (boolean)
* allowPopups (boolean)
* userContextId (unsigned int)
*/
function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerURI) {
var params;
@ -220,6 +222,7 @@ function openLinkIn(url, where, params) {
var aAllowPinnedTabHostChange = !!params.allowPinnedTabHostChange;
var aNoReferrer = params.noReferrer;
var aAllowPopups = !!params.allowPopups;
var aUserContextId = params.userContextId;
var aIndicateErrorPageLoad = params.indicateErrorPageLoad;
var aPrincipal = params.originPrincipal;
var aTriggeringPrincipal = params.triggeringPrincipal;
@ -265,6 +268,7 @@ function openLinkIn(url, where, params) {
function useOAForPrincipal(principal) {
if (principal && principal.isCodebasePrincipal) {
let attrs = {
userContextId: aUserContextId,
privateBrowsingId: aIsPrivate || (w && PrivateBrowsingUtils.isWindowPrivate(w)),
};
return Services.scriptSecurityManager.createCodebasePrincipal(principal.URI, attrs);
@ -311,12 +315,17 @@ function openLinkIn(url, where, params) {
createInstance(Ci.nsISupportsPRUint32);
referrerPolicySupports.data = aReferrerPolicy;
var userContextIdSupports = Cc["@mozilla.org/supports-PRUint32;1"].
createInstance(Ci.nsISupportsPRUint32);
userContextIdSupports.data = aUserContextId;
sa.appendElement(wuri, /* weak =*/ false);
sa.appendElement(charset, /* weak =*/ false);
sa.appendElement(referrerURISupports, /* weak =*/ false);
sa.appendElement(aPostData, /* weak =*/ false);
sa.appendElement(allowThirdPartyFixupSupports, /* weak =*/ false);
sa.appendElement(referrerPolicySupports, /* weak =*/ false);
sa.appendElement(userContextIdSupports, /* weak =*/ false);
sa.appendElement(aPrincipal, /* weak =*/ false);
sa.appendElement(aTriggeringPrincipal, /* weak =*/ false);
@ -409,7 +418,8 @@ function openLinkIn(url, where, params) {
flags: flags,
referrerURI: aNoReferrer ? null : aReferrerURI,
referrerPolicy: aReferrerPolicy,
postData: aPostData
postData: aPostData,
userContextId: aUserContextId
});
browserUsedForLoad = aCurrentBrowser;
break;
@ -428,6 +438,7 @@ function openLinkIn(url, where, params) {
skipAnimation: aSkipTabAnimation,
allowMixedContent: aAllowMixedContent,
noReferrer: aNoReferrer,
userContextId: aUserContextId,
originPrincipal: aPrincipal,
triggeringPrincipal: aTriggeringPrincipal,
});
@ -471,6 +482,74 @@ function checkForMiddleClick(node, event) {
}
}
// Populate a menu with user-context menu items. This method should be called
// by onpopupshowing passing the event as first argument.
function createUserContextMenu(event, isContextMenu = false, excludeUserContextId = 0) {
while (event.target.hasChildNodes()) {
event.target.removeChild(event.target.firstChild);
}
let bundle = document.getElementById("bundle_browser");
let docfrag = document.createDocumentFragment();
// If we are excluding a userContextId, we want to add a 'no-container' item.
if (excludeUserContextId) {
let menuitem = document.createElement("menuitem");
menuitem.setAttribute("data-usercontextid", "0");
menuitem.setAttribute("label", bundle.getString("userContextNone.label"));
menuitem.setAttribute("accesskey", bundle.getString("userContextNone.accesskey"));
// We don't set an oncommand/command attribute because if we have
// to exclude a userContextId we are generating the contextMenu and
// isContextMenu will be true.
docfrag.appendChild(menuitem);
let menuseparator = document.createElement("menuseparator");
docfrag.appendChild(menuseparator);
}
ContextualIdentityService.getIdentities().forEach(identity => {
if (identity.userContextId == excludeUserContextId) {
return;
}
let menuitem = document.createElement("menuitem");
menuitem.setAttribute("data-usercontextid", identity.userContextId);
menuitem.setAttribute("label", ContextualIdentityService.getUserContextLabel(identity.userContextId));
if (identity.accessKey) {
menuitem.setAttribute("accesskey", bundle.getString(identity.accessKey));
}
menuitem.classList.add("menuitem-iconic");
menuitem.setAttribute("data-identity-color", identity.color);
if (!isContextMenu) {
menuitem.setAttribute("command", "Browser:NewUserContextTab");
}
menuitem.setAttribute("data-identity-icon", identity.icon);
docfrag.appendChild(menuitem);
});
if (!isContextMenu) {
docfrag.appendChild(document.createElement("menuseparator"));
let menuitem = document.createElement("menuitem");
menuitem.setAttribute("label",
bundle.getString("userContext.aboutPage.label"));
menuitem.setAttribute("accesskey",
bundle.getString("userContext.aboutPage.accesskey"));
menuitem.setAttribute("command", "Browser:OpenAboutContainers");
docfrag.appendChild(menuitem);
}
event.target.appendChild(docfrag);
return true;
}
// Closes all popups that are ancestors of the node.
function closeMenus(node)
{