зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1634796 - Add a panel that warns users before switching tabs when sharing the window over WebRTC. r=johannh,fluent-reviewers,flod
Differential Revision: https://phabricator.services.mozilla.com/D73734
This commit is contained in:
Родитель
ca8cca32cb
Коммит
27a590bd9e
|
@ -1662,6 +1662,9 @@ pref("privacy.userContext.newTabContainerOnLeftClick.enabled", false);
|
|||
pref("privacy.webrtc.allowSilencingNotifications", false);
|
||||
// Set to true to use the legacy WebRTC global indicator
|
||||
pref("privacy.webrtc.legacyGlobalIndicator", true);
|
||||
// Set to true to enable a warning displayed when attempting
|
||||
// to switch tabs in a window that's being shared over WebRTC.
|
||||
pref("privacy.webrtc.sharedTabWarning", false);
|
||||
|
||||
// Start the browser in e10s mode
|
||||
pref("browser.tabs.remote.autostart", true);
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
/* 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/. */
|
||||
|
||||
/* eslint-env mozilla/browser-window */
|
||||
|
||||
/**
|
||||
* Utility object to handle WebRTC shared tab warnings.
|
||||
*/
|
||||
var gSharedTabWarning = {
|
||||
/**
|
||||
* Called externally by gBrowser to determine if we're
|
||||
* in a state such that we'd want to cancel the tab switch
|
||||
* and show the tab switch warning panel instead.
|
||||
*
|
||||
* @param tab (<tab>)
|
||||
* The tab being switched to.
|
||||
* @returns boolean
|
||||
* True if the panel will be shown, and the tab switch should
|
||||
* be cancelled.
|
||||
*/
|
||||
willShowSharedTabWarning(tab) {
|
||||
if (!this._sharedTabWarningEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let shareState = webrtcUI.getWindowShareState(window);
|
||||
if (shareState == webrtcUI.SHARING_NONE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!webrtcUI.shouldShowSharedTabWarning(tab)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this._createSharedTabWarningIfNeeded();
|
||||
let panel = document.getElementById("sharing-tabs-warning-panel");
|
||||
let hbox = panel.firstChild;
|
||||
|
||||
if (shareState == webrtcUI.SHARING_SCREEN) {
|
||||
hbox.setAttribute("type", "screen");
|
||||
panel.setAttribute(
|
||||
"aria-labelledby",
|
||||
"sharing-screen-warning-panel-header-span"
|
||||
);
|
||||
} else {
|
||||
hbox.setAttribute("type", "window");
|
||||
panel.setAttribute(
|
||||
"aria-labelledby",
|
||||
"sharing-window-warning-panel-header-span"
|
||||
);
|
||||
}
|
||||
|
||||
let allowForSessionCheckbox = document.getElementById(
|
||||
"sharing-warning-disable-for-session"
|
||||
);
|
||||
allowForSessionCheckbox.checked = false;
|
||||
|
||||
panel.openPopup(tab, "bottomcenter topleft", 0, 0);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called by the tab switch warning panel after it has
|
||||
* shown.
|
||||
*/
|
||||
sharedTabWarningShown() {
|
||||
let allowButton = document.getElementById("sharing-warning-proceed-to-tab");
|
||||
allowButton.focus();
|
||||
},
|
||||
|
||||
/**
|
||||
* Called by the button in the tab switch warning panel
|
||||
* to allow the switch to occur.
|
||||
*/
|
||||
allowSharedTabSwitch() {
|
||||
let panel = document.getElementById("sharing-tabs-warning-panel");
|
||||
let allowForSession = document.getElementById(
|
||||
"sharing-warning-disable-for-session"
|
||||
).checked;
|
||||
|
||||
let tab = panel.anchorNode;
|
||||
webrtcUI.allowSharedTabSwitch(tab, allowForSession);
|
||||
this._hideSharedTabWarning();
|
||||
},
|
||||
|
||||
/**
|
||||
* Called externally by gBrowser when a tab has been added.
|
||||
* When this occurs, if we're sharing this window, we notify
|
||||
* the webrtcUI module to exempt the new tab from the tab switch
|
||||
* warning, since the user opened it while they were already
|
||||
* sharing.
|
||||
*
|
||||
* @param tab (<tab>)
|
||||
* The tab being opened.
|
||||
*/
|
||||
tabAdded(tab) {
|
||||
if (this._sharedTabWarningEnabled) {
|
||||
let shareState = webrtcUI.getWindowShareState(window);
|
||||
if (shareState != webrtcUI.SHARING_NONE) {
|
||||
webrtcUI.tabAddedWhileSharing(tab);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
get _sharedTabWarningEnabled() {
|
||||
delete this._sharedTabWarningEnabled;
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this,
|
||||
"_sharedTabWarningEnabled",
|
||||
"privacy.webrtc.sharedTabWarning"
|
||||
);
|
||||
return this._sharedTabWarningEnabled;
|
||||
},
|
||||
|
||||
/**
|
||||
* Internal method for hiding the tab switch warning panel.
|
||||
*/
|
||||
_hideSharedTabWarning() {
|
||||
let panel = document.getElementById("sharing-tabs-warning-panel");
|
||||
if (panel) {
|
||||
panel.hidePopup();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Inserts the tab switch warning panel into the DOM
|
||||
* if it hasn't been done already yet.
|
||||
*/
|
||||
_createSharedTabWarningIfNeeded() {
|
||||
// Lazy load the panel the first time we need to display it.
|
||||
if (!document.getElementById("sharing-tabs-warning-panel")) {
|
||||
let template = document.getElementById(
|
||||
"sharing-tabs-warning-panel-template"
|
||||
);
|
||||
template.replaceWith(template.content);
|
||||
}
|
||||
},
|
||||
};
|
|
@ -245,6 +245,11 @@ XPCOMUtils.defineLazyScriptGetter(
|
|||
"A11yUtils",
|
||||
"chrome://browser/content/browser-a11yUtils.js"
|
||||
);
|
||||
XPCOMUtils.defineLazyScriptGetter(
|
||||
this,
|
||||
"gSharedTabWarning",
|
||||
"chrome://browser/content/browser-webrtc.js"
|
||||
);
|
||||
|
||||
// lazy service getters
|
||||
|
||||
|
|
|
@ -83,6 +83,7 @@
|
|||
<link rel="localization" href="browser/sidebarMenu.ftl"/>
|
||||
<link rel="localization" href="browser/allTabsMenu.ftl"/>
|
||||
<link rel="localization" href="browser/places.ftl"/>
|
||||
<link rel="localization" href="preview/popup-notifications.ftl"/>
|
||||
|
||||
<title>&mainWindow.title;</title>
|
||||
|
||||
|
@ -685,6 +686,40 @@
|
|||
crop="end"/>
|
||||
</hbox>
|
||||
</hbox>
|
||||
|
||||
<html:template id="sharing-tabs-warning-panel-template">
|
||||
<panel id="sharing-tabs-warning-panel"
|
||||
role="alert"
|
||||
flip="slide"
|
||||
type="arrow"
|
||||
orient="vertical"
|
||||
ignorekeys="true"
|
||||
consumeoutsideclicks="never"
|
||||
norolluponanchor="true"
|
||||
onpopupshown="gSharedTabWarning.sharedTabWarningShown();">
|
||||
<hbox type="window" align="start">
|
||||
<image class="screen-icon popup-notification-icon"></image>
|
||||
<vbox flex="1" pack="start">
|
||||
<label>
|
||||
<html:span id="sharing-warning-window-panel-header"
|
||||
role="heading"
|
||||
aria-level="1"
|
||||
data-l10n-id="sharing-warning-window"/>
|
||||
<html:span id="sharing-warning-screen-panel-header"
|
||||
role="heading"
|
||||
aria-level="1"
|
||||
data-l10n-id="sharing-warning-screen"/>
|
||||
</label>
|
||||
<hbox align="center">
|
||||
<button id="sharing-warning-proceed-to-tab" oncommand="gSharedTabWarning.allowSharedTabSwitch();" flex="1" data-l10n-id="sharing-warning-proceed-to-tab"/>
|
||||
</hbox>
|
||||
<hbox pack="start">
|
||||
<checkbox id="sharing-warning-disable-for-session" data-l10n-id="sharing-warning-disable-for-session"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</hbox>
|
||||
</panel>
|
||||
</html:template>
|
||||
</popupset>
|
||||
<box id="appMenu-viewCache" hidden="true"/>
|
||||
|
||||
|
|
|
@ -17,3 +17,12 @@ popup-screen-sharing-never =
|
|||
|
||||
popup-silence-notifications-checkbox = Disable notifications from { -brand-short-name } while sharing
|
||||
popup-silence-notifications-checkbox-warning = { -brand-short-name } will not display notifications while you are sharing.
|
||||
|
||||
## WebRTC window or screen share tab switch warning
|
||||
|
||||
sharing-warning-window = You are sharing { -brand-short-name }. Other people can see when you switch to a new tab.
|
||||
sharing-warning-screen = You are sharing your entire screen. Other people can see when you switch to a new tab.
|
||||
sharing-warning-proceed-to-tab =
|
||||
.label = Proceed to Tab
|
||||
sharing-warning-disable-for-session =
|
||||
.label = Disable sharing protection for this session
|
||||
|
|
|
@ -292,7 +292,10 @@
|
|||
on_dragstart(event) {
|
||||
if (event.eventPhase == Event.CAPTURING_PHASE) {
|
||||
this.style.MozUserFocus = "";
|
||||
} else if (this.mOverCloseButton) {
|
||||
} else if (
|
||||
this.mOverCloseButton ||
|
||||
gSharedTabWarning.willShowSharedTabWarning(this)
|
||||
) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
@ -354,6 +357,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
if (gSharedTabWarning.willShowSharedTabWarning(this)) {
|
||||
eventMaySelectTab = false;
|
||||
}
|
||||
|
||||
if (eventMaySelectTab) {
|
||||
super.on_mousedown(event);
|
||||
}
|
||||
|
|
|
@ -293,7 +293,10 @@
|
|||
},
|
||||
|
||||
set selectedTab(val) {
|
||||
if (gNavToolbox.collapsed && !this._allowTabChange) {
|
||||
if (
|
||||
gSharedTabWarning.willShowSharedTabWarning(val) ||
|
||||
(gNavToolbox.collapsed && !this._allowTabChange)
|
||||
) {
|
||||
return this.tabbox.selectedTab;
|
||||
}
|
||||
// Update the tab
|
||||
|
@ -2855,6 +2858,8 @@
|
|||
this._notifyPinnedStatus(t);
|
||||
}
|
||||
|
||||
gSharedTabWarning.tabAdded(t);
|
||||
|
||||
return t;
|
||||
},
|
||||
|
||||
|
|
|
@ -229,10 +229,6 @@ var whitelist = [
|
|||
// Referenced from the screenshots webextension
|
||||
{ file: "resource://app/localization/en-US/browser/screenshots.ftl" },
|
||||
|
||||
// This file is referenced from WebRTCParent.jsm. Once this localization
|
||||
// file gets moved to the locales directory, this should get removed.
|
||||
{ file: "resource://app/localization/en-US/preview/popup-notifications.ftl" },
|
||||
|
||||
// services/fxaccounts/RustFxAccount.js
|
||||
{ file: "resource://gre/modules/RustFxAccount.js" },
|
||||
];
|
||||
|
|
|
@ -57,6 +57,7 @@ browser.jar:
|
|||
content/browser/browser-toolbarKeyNav.js (content/browser-toolbarKeyNav.js)
|
||||
content/browser/browser-thumbnails.js (content/browser-thumbnails.js)
|
||||
content/browser/browser-graphics-utils.js (content/browser-graphics-utils.js)
|
||||
content/browser/browser-webrtc.js (content/browser-webrtc.js)
|
||||
content/browser/tab-content.js (content/tab-content.js)
|
||||
content/browser/defaultthemes/1.header.jpg (content/defaultthemes/1.header.jpg)
|
||||
content/browser/defaultthemes/1.icon.jpg (content/defaultthemes/1.icon.jpg)
|
||||
|
|
|
@ -74,6 +74,9 @@ var webrtcUI = {
|
|||
// Set of browser windows that are being shared over WebRTC.
|
||||
sharedWindows: new WeakSet(),
|
||||
sharingScreen: false,
|
||||
allowedSharedBrowsers: new WeakSet(),
|
||||
allowTabSwitchesForSession: false,
|
||||
tabSwitchCountForSession: 0,
|
||||
|
||||
// Map of browser elements to indicator data.
|
||||
perTabIndicators: new Map(),
|
||||
|
@ -298,9 +301,14 @@ var webrtcUI = {
|
|||
};
|
||||
}
|
||||
|
||||
// Reset our internal notion of whether or not we're sharing
|
||||
// a screen or browser window. Now we'll go through the shared
|
||||
// devices and re-determine what's being shared.
|
||||
let sharingBrowserWindow = false;
|
||||
let sharedWindowRawDeviceIds = new Set();
|
||||
this.sharingScreen = false;
|
||||
let suppressNotifications = false;
|
||||
|
||||
for (let stream of this._streams) {
|
||||
let { state } = stream;
|
||||
suppressNotifications |= state.suppressNotifications;
|
||||
|
@ -317,6 +325,15 @@ var webrtcUI = {
|
|||
} else if (mediaSource == "screen") {
|
||||
this.sharingScreen = true;
|
||||
}
|
||||
|
||||
// If the user has granted a particular site the ability
|
||||
// to get a stream from a window or screen, we will
|
||||
// presume that it's exempt from the tab switch warning.
|
||||
//
|
||||
// We use the permanentKey here so that the allowing of
|
||||
// the tab survives tab tear-in and tear-out.
|
||||
let browser = stream.topBrowsingContext.embedderElement;
|
||||
this.allowedSharedBrowsers.add(browser.permanentKey);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,9 +351,28 @@ var webrtcUI = {
|
|||
}
|
||||
if (sharedWindowRawDeviceIds.has(rawDeviceId)) {
|
||||
this.sharedWindows.add(win);
|
||||
|
||||
// If we've shared a window, then the initially selected tab
|
||||
// in that window should be exempt from tab switch warnings,
|
||||
// since it's already been shared.
|
||||
let selectedBrowser = win.gBrowser.selectedBrowser;
|
||||
this.allowedSharedBrowsers.add(selectedBrowser.permanentKey);
|
||||
|
||||
sharingBrowserWindow = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Since we're not sharing a screen or browser window,
|
||||
// we can clear these state variables, which are used
|
||||
// to warn users on tab switching when sharing. These
|
||||
// are safe to reset even if we hadn't been sharing
|
||||
// the screen or browser window already.
|
||||
if (!this.sharingScreen && !sharingBrowserWindow) {
|
||||
this.allowedSharedBrowsers = new WeakSet();
|
||||
this.allowTabSwitchesForSession = false;
|
||||
this.tabSwitchCountForSession = 0;
|
||||
}
|
||||
|
||||
if (
|
||||
Services.prefs.getBoolPref(
|
||||
"privacy.webrtc.allowSilencingNotifications",
|
||||
|
@ -556,6 +592,40 @@ var webrtcUI = {
|
|||
}
|
||||
return this.SHARING_NONE;
|
||||
},
|
||||
|
||||
tabAddedWhileSharing(tab) {
|
||||
this.allowedSharedBrowsers.add(tab.linkedBrowser.permanentKey);
|
||||
},
|
||||
|
||||
shouldShowSharedTabWarning(tab) {
|
||||
let browser = tab.linkedBrowser;
|
||||
// We want the user to be able to switch to one tab after starting
|
||||
// to share their window or screen. The presumption here is that
|
||||
// most users will have a single window with multiple tabs, where
|
||||
// the selected tab will be the one with the screen or window
|
||||
// sharing web application, and it's most likely that the contents
|
||||
// that the user wants to share are in another tab that they'll
|
||||
// switch to immediately upon sharing. These presumptions are based
|
||||
// on research that our user research team did with users using
|
||||
// video conferencing web applications.
|
||||
if (!this.tabSwitchCountForSession) {
|
||||
this.allowedSharedBrowsers.add(browser.permanentKey);
|
||||
}
|
||||
|
||||
this.tabSwitchCountForSession++;
|
||||
return (
|
||||
!this.allowTabSwitchesForSession &&
|
||||
!this.allowedSharedBrowsers.has(browser.permanentKey)
|
||||
);
|
||||
},
|
||||
|
||||
allowSharedTabSwitch(tab, allowForSession) {
|
||||
let browser = tab.linkedBrowser;
|
||||
let gBrowser = browser.getTabBrowser();
|
||||
this.allowedSharedBrowsers.add(browser.permanentKey);
|
||||
gBrowser.selectedTab = tab;
|
||||
this.allowTabSwitchesForSession = allowForSession;
|
||||
},
|
||||
};
|
||||
|
||||
function getGlobalIndicator() {
|
||||
|
|
|
@ -595,3 +595,28 @@ menupopup::part(drop-indicator) {
|
|||
font-size: 1.18em;
|
||||
%endif
|
||||
}
|
||||
|
||||
#sharing-tabs-warning-panel > hbox[type="window"] > vbox > label > #sharing-warning-screen-panel-header,
|
||||
#sharing-tabs-warning-panel > hbox[type="screen"] > vbox > label > #sharing-warning-window-panel-header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#sharing-tabs-warning-panel {
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
#sharing-warning-proceed-to-tab {
|
||||
-moz-appearance: none;
|
||||
border-style: none;
|
||||
margin: 0;
|
||||
background-color: rgb(0,96,223);
|
||||
color: rgb(255,255,255);
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#sharing-warning-proceed-to-tab:hover {
|
||||
background-color: rgb(0,62,170);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче