Merge mozilla-central to autoland. a=merge CLOSED TREE

This commit is contained in:
Bogdan Tara 2018-08-11 06:46:31 +03:00
commit dfe849c923
113 changed files with 2186 additions and 1121 deletions

View file

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please # changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more. # don't change CLOBBER for WebIDL changes any more.
Bug 1435409 - move Android to a non-NDK clang Bug 1433158 - libvpx library update requires a clobber

View file

@ -17,16 +17,17 @@ if (Utils.MozBuildApp === "mobile/android") {
const GECKOVIEW_MESSAGE = { const GECKOVIEW_MESSAGE = {
ACTIVATE: "GeckoView:AccessibilityActivate", ACTIVATE: "GeckoView:AccessibilityActivate",
VIEW_FOCUSED: "GeckoView:AccessibilityViewFocused",
LONG_PRESS: "GeckoView:AccessibilityLongPress",
BY_GRANULARITY: "GeckoView:AccessibilityByGranularity", BY_GRANULARITY: "GeckoView:AccessibilityByGranularity",
CLIPBOARD: "GeckoView:AccessibilityClipboard",
EXPLORE_BY_TOUCH: "GeckoView:AccessibilityExploreByTouch",
LONG_PRESS: "GeckoView:AccessibilityLongPress",
NEXT: "GeckoView:AccessibilityNext", NEXT: "GeckoView:AccessibilityNext",
PREVIOUS: "GeckoView:AccessibilityPrevious", PREVIOUS: "GeckoView:AccessibilityPrevious",
SCROLL_BACKWARD: "GeckoView:AccessibilityScrollBackward", SCROLL_BACKWARD: "GeckoView:AccessibilityScrollBackward",
SCROLL_FORWARD: "GeckoView:AccessibilityScrollForward", SCROLL_FORWARD: "GeckoView:AccessibilityScrollForward",
EXPLORE_BY_TOUCH: "GeckoView:AccessibilityExploreByTouch", SELECT: "GeckoView:AccessibilitySelect",
SET_SELECTION: "GeckoView:AccessibilitySetSelection", SET_SELECTION: "GeckoView:AccessibilitySetSelection",
CLIPBOARD: "GeckoView:AccessibilityClipboard", VIEW_FOCUSED: "GeckoView:AccessibilityViewFocused",
}; };
const ACCESSFU_MESSAGE = { const ACCESSFU_MESSAGE = {
@ -238,6 +239,9 @@ var AccessFu = {
case GECKOVIEW_MESSAGE.CLIPBOARD: case GECKOVIEW_MESSAGE.CLIPBOARD:
this.Input.clipboard(data); this.Input.clipboard(data);
break; break;
case GECKOVIEW_MESSAGE.SELECT:
this.Input.selectCurrent(data);
break;
} }
}, },
@ -348,6 +352,11 @@ var Input = {
mm.sendAsyncMessage("AccessFu:Activate", { offset: 0 }); mm.sendAsyncMessage("AccessFu:Activate", { offset: 0 });
}, },
selectCurrent: function selectCurrent(aData) {
let mm = Utils.getMessageManager();
mm.sendAsyncMessage("AccessFu:Select", aData);
},
doScroll: function doScroll(aDetails, aBrowser) { doScroll: function doScroll(aDetails, aBrowser) {
let horizontal = aDetails.horizontal; let horizontal = aDetails.horizontal;
let page = aDetails.page; let page = aDetails.page;

View file

@ -33,15 +33,16 @@ function ContentControl(aContentScope) {
} }
this.ContentControl.prototype = { this.ContentControl.prototype = {
messagesOfInterest: ["AccessFu:MoveCursor", messagesOfInterest: ["AccessFu:Activate",
"AccessFu:ClearCursor",
"AccessFu:MoveToPoint",
"AccessFu:AutoMove",
"AccessFu:Activate",
"AccessFu:MoveByGranularity",
"AccessFu:AndroidScroll", "AccessFu:AndroidScroll",
"AccessFu:SetSelection", "AccessFu:AutoMove",
"AccessFu:Clipboard"], "AccessFu:ClearCursor",
"AccessFu:Clipboard",
"AccessFu:MoveByGranularity",
"AccessFu:MoveCursor",
"AccessFu:MoveToPoint",
"AccessFu:Select",
"AccessFu:SetSelection"],
start: function cc_start() { start: function cc_start() {
let cs = this._contentScope.get(); let cs = this._contentScope.get();
@ -180,6 +181,16 @@ this.ContentControl.prototype = {
this.autoMove(null, aMessage.json); this.autoMove(null, aMessage.json);
}, },
handleSelect: function cc_handleSelect(aMessage) {
const vc = this.vc;
if (!this.sendToChild(vc, aMessage, null, true)) {
const acc = vc.position;
if (Utils.getState(acc).contains(States.SELECTABLE)) {
this.handleActivate(aMessage);
}
}
},
handleActivate: function cc_handleActivate(aMessage) { handleActivate: function cc_handleActivate(aMessage) {
let activateAccessible = (aAccessible) => { let activateAccessible = (aAccessible) => {
Logger.debug(() => { Logger.debug(() => {
@ -222,7 +233,7 @@ this.ContentControl.prototype = {
if (!Utils.getState(aAccessible).contains(States.CHECKABLE) && if (!Utils.getState(aAccessible).contains(States.CHECKABLE) &&
!Utils.getState(aAccessible).contains(States.SELECTABLE)) { !Utils.getState(aAccessible).contains(States.SELECTABLE)) {
this._contentScope.get().sendAsyncMessage("AccessFu:Present", this._contentScope.get().sendAsyncMessage("AccessFu:Present",
Presentation.actionInvoked(aAccessible, "click")); Presentation.actionInvoked());
} }
}; };

View file

@ -93,25 +93,26 @@ this.EventManager.prototype = {
return ["DOMEvent", aEvent.type]; return ["DOMEvent", aEvent.type];
}); });
// The target could be an element, document or window
const win = aEvent.target.ownerGlobal;
try { try {
switch (aEvent.type) { switch (aEvent.type) {
case "wheel": case "wheel":
{ {
let delta = aEvent.deltaX || aEvent.deltaY; let delta = aEvent.deltaX || aEvent.deltaY;
this.contentControl.autoMove( this.contentControl.autoMove(
null, null,
{ moveMethod: delta > 0 ? "moveNext" : "movePrevious", { moveMethod: delta > 0 ? "moveNext" : "movePrevious",
onScreenOnly: true, noOpIfOnScreen: true, delay: 500 }); onScreenOnly: true, noOpIfOnScreen: true, delay: 500 });
break; break;
} }
case "scroll": case "scroll":
case "resize": this.present(Presentation.viewportScrolled(win));
{ case "resize":
// the target could be an element, document or window {
let window = aEvent.target.ownerGlobal; this.present(Presentation.viewportChanged(win));
this.present(Presentation.viewportChanged(window)); break;
break; }
}
} }
} catch (x) { } catch (x) {
Logger.logException(x, "Error handling DOM event"); Logger.logException(x, "Error handling DOM event");
@ -465,7 +466,9 @@ this.EventManager.prototype = {
}, },
present: function present(aPresentationData) { present: function present(aPresentationData) {
this.sendMsgFunc("AccessFu:Present", aPresentationData); if (aPresentationData && aPresentationData.length > 0) {
this.sendMsgFunc("AccessFu:Present", aPresentationData);
}
}, },
onStateChange: function onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) { onStateChange: function onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {

View file

@ -116,21 +116,16 @@ class AndroidPresentor {
*/ */
selected(aAccessible) { selected(aAccessible) {
return [{ return [{
eventType: AndroidEvents.VIEW_CLICKED, eventType: AndroidEvents.VIEW_SELECTED,
selected: Utils.getState(aAccessible).contains(States.SELECTED) selected: Utils.getState(aAccessible).contains(States.SELECTED)
}]; }];
} }
/** /**
* An object's action has been invoked. * An object's action has been invoked.
* @param {nsIAccessible} aAccessible the object that has been invoked.
* @param {string} aActionName the name of the action.
*/ */
actionInvoked(aAccessible, aActionName) { actionInvoked() {
return [{ return [{ eventType: AndroidEvents.VIEW_CLICKED }];
eventType: AndroidEvents.VIEW_CLICKED,
text: Utils.localize(UtteranceGenerator.genForAction(aAccessible, aActionName))
}];
} }
/** /**
@ -226,32 +221,40 @@ class AndroidPresentor {
} }
/** /**
* The viewport has changed, either a scroll, pan, zoom, or * The viewport has changed because of scroll.
* landscape/portrait toggle. * @param {Window} aWindow window of viewport that changed.
*/
viewportScrolled(aWindow) {
const { windowUtils, devicePixelRatio } = aWindow;
const resolution = { value: 1 };
windowUtils.getResolution(resolution);
const scale = devicePixelRatio * resolution.value;
return [{
eventType: AndroidEvents.VIEW_SCROLLED,
scrollX: aWindow.scrollX * scale,
scrollY: aWindow.scrollY * scale,
maxScrollX: aWindow.scrollMaxX * scale,
maxScrollY: aWindow.scrollMaxY * scale,
}];
}
/**
* The viewport has changed, either a pan, zoom, or landscape/portrait toggle.
* @param {Window} aWindow window of viewport that changed. * @param {Window} aWindow window of viewport that changed.
*/ */
viewportChanged(aWindow) { viewportChanged(aWindow) {
let currentContext = this.displayedAccessibles.get(aWindow); const currentContext = this.displayedAccessibles.get(aWindow);
if (!currentContext) {
let events = [{ return;
eventType: AndroidEvents.VIEW_SCROLLED,
scrollX: aWindow.scrollX,
scrollY: aWindow.scrollY,
maxScrollX: aWindow.scrollMaxX,
maxScrollY: aWindow.scrollMaxY,
}];
if (currentContext) {
let currentAcc = currentContext.accessibleForBounds;
if (Utils.isAliveAndVisible(currentAcc)) {
events.push({
eventType: AndroidEvents.WINDOW_CONTENT_CHANGED,
bounds: Utils.getBounds(currentAcc)
});
}
} }
return events; const currentAcc = currentContext.accessibleForBounds;
if (Utils.isAliveAndVisible(currentAcc)) {
return [{
eventType: AndroidEvents.WINDOW_STATE_CHANGED,
bounds: Utils.getBounds(currentAcc)
}];
}
} }
/** /**

View file

@ -1491,11 +1491,6 @@ pref("browser.contentblocking.ui.enabled", false);
pref("privacy.trackingprotection.introCount", 0); pref("privacy.trackingprotection.introCount", 0);
pref("privacy.trackingprotection.introURL", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/tracking-protection/start/"); pref("privacy.trackingprotection.introURL", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/tracking-protection/start/");
#ifdef NIGHTLY_BUILD
pref("privacy.trackingprotection.appMenuToggle.enabled", true);
#else
pref("privacy.trackingprotection.appMenuToggle.enabled", false);
#endif
// Always enable newtab segregation using containers // Always enable newtab segregation using containers
pref("privacy.usercontext.about_newtab_segregation.enabled", true); pref("privacy.usercontext.about_newtab_segregation.enabled", true);

View file

@ -125,9 +125,9 @@ FindCharInUnicodeString(const UNICODE_STRING& aStr, WCHAR aChar, uint16_t& aPos,
inline bool inline bool
IsHexDigit(WCHAR aChar) IsHexDigit(WCHAR aChar)
{ {
return aChar >= L'0' && aChar <= L'9' || return (aChar >= L'0' && aChar <= L'9') ||
aChar >= L'A' && aChar <= L'F' || (aChar >= L'A' && aChar <= L'F') ||
aChar >= L'a' && aChar <= L'f'; (aChar >= L'a' && aChar <= L'f');
} }
inline bool inline bool

View file

@ -5,8 +5,10 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#include "NativeNt.h" #include "NativeNt.h"
#include "mozilla/UniquePtr.h"
#include <stdio.h> #include <stdio.h>
#include <windows.h>
const wchar_t kNormal[] = L"Foo.dll"; const wchar_t kNormal[] = L"Foo.dll";
const wchar_t kHex12[] = L"Foo.ABCDEF012345.dll"; const wchar_t kHex12[] = L"Foo.ABCDEF012345.dll";
@ -34,6 +36,7 @@ const char kFailFmt[] = "TEST-FAILED | NativeNt | %s(%s) should have returned %s
#define EXPECT_SUCCESS(fn, varName) \ #define EXPECT_SUCCESS(fn, varName) \
RUN_TEST(fn, varName, true) RUN_TEST(fn, varName, true)
using namespace mozilla;
using namespace mozilla::nt; using namespace mozilla::nt;
int main(int argc, char* argv[]) int main(int argc, char* argv[])
@ -92,6 +95,53 @@ int main(int argc, char* argv[])
return 1; return 1;
} }
const wchar_t kKernel32[] = L"kernel32.dll";
DWORD verInfoSize = ::GetFileVersionInfoSizeW(kKernel32, nullptr);
if (!verInfoSize) {
printf("TEST-FAILED | NativeNt | Call to GetFileVersionInfoSizeW failed with code %lu\n",
::GetLastError());
return 1;
}
auto verInfoBuf = MakeUnique<char[]>(verInfoSize);
if (!::GetFileVersionInfoW(kKernel32, 0, verInfoSize, verInfoBuf.get())) {
printf("TEST-FAILED | NativeNt | Call to GetFileVersionInfoW failed with code %lu\n",
::GetLastError());
return 1;
}
UINT len;
VS_FIXEDFILEINFO* fixedFileInfo = nullptr;
if (!::VerQueryValueW(verInfoBuf.get(), L"\\", (LPVOID*)&fixedFileInfo, &len)) {
printf("TEST-FAILED | NativeNt | Call to VerQueryValueW failed with code %lu\n",
::GetLastError());
return 1;
}
const uint64_t expectedVersion =
(static_cast<uint64_t>(fixedFileInfo->dwFileVersionMS) << 32) |
static_cast<uint64_t>(fixedFileInfo->dwFileVersionLS);
PEHeaders k32headers(::GetModuleHandleW(kKernel32));
if (!k32headers) {
printf("TEST-FAILED | NativeNt | Failed parsing kernel32.dll's PE headers\n");
return 1;
}
uint64_t version;
if (!k32headers.GetVersionInfo(version)) {
printf("TEST-FAILED | NativeNt | Unable to obtain version information from kernel32.dll\n");
return 1;
}
if (version != expectedVersion) {
printf("TEST-FAILED | NativeNt | kernel32.dll's detected version "
"(0x%016llX) does not match expected version (0x%016llX)\n",
version, expectedVersion);
return 1;
}
return 0; return 0;
} }

View file

@ -13,6 +13,7 @@ LOCAL_INCLUDES += [
] ]
OS_LIBS += [ OS_LIBS += [
'mincore',
'ntdll', 'ntdll',
] ]

View file

@ -2,21 +2,187 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var FastBlock = {
PREF_ENABLED: "browser.fastblock.enabled",
get categoryItem() {
delete this.categoryItem;
return this.categoryItem = document.getElementById("identity-popup-content-blocking-category-fastblock");
},
init() {
XPCOMUtils.defineLazyPreferenceGetter(this, "enabled", this.PREF_ENABLED, false);
},
};
var TrackingProtection = { var TrackingProtection = {
// If the user ignores the doorhanger, we stop showing it after some time.
MAX_INTROS: 20,
PREF_ENABLED_GLOBALLY: "privacy.trackingprotection.enabled", PREF_ENABLED_GLOBALLY: "privacy.trackingprotection.enabled",
PREF_ENABLED_IN_PRIVATE_WINDOWS: "privacy.trackingprotection.pbmode.enabled", PREF_ENABLED_IN_PRIVATE_WINDOWS: "privacy.trackingprotection.pbmode.enabled",
PREF_APP_MENU_TOGGLE: "privacy.trackingprotection.appMenuToggle.enabled",
PREF_ANIMATIONS_ENABLED: "toolkit.cosmeticAnimations.enabled",
enabledGlobally: false, enabledGlobally: false,
enabledInPrivateWindows: false, enabledInPrivateWindows: false,
container: null,
get categoryItem() {
delete this.categoryItem;
return this.categoryItem =
document.getElementById("identity-popup-content-blocking-category-tracking-protection");
},
strings: {
get enableTooltip() {
delete this.enableTooltip;
return this.enableTooltip =
gNavigatorBundle.getString("trackingProtection.toggle.enable.tooltip");
},
get disableTooltip() {
delete this.disableTooltip;
return this.disableTooltip =
gNavigatorBundle.getString("trackingProtection.toggle.disable.tooltip");
},
get disableTooltipPB() {
delete this.disableTooltipPB;
return this.disableTooltipPB =
gNavigatorBundle.getString("trackingProtection.toggle.disable.pbmode.tooltip");
},
get enableTooltipPB() {
delete this.enableTooltipPB;
return this.enableTooltipPB =
gNavigatorBundle.getString("trackingProtection.toggle.enable.pbmode.tooltip");
},
},
init() {
this.updateEnabled();
this.enabledHistogramAdd(this.enabledGlobally);
this.disabledPBMHistogramAdd(!this.enabledInPrivateWindows);
Services.prefs.addObserver(this.PREF_ENABLED_GLOBALLY, this);
Services.prefs.addObserver(this.PREF_ENABLED_IN_PRIVATE_WINDOWS, this);
},
uninit() {
Services.prefs.removeObserver(this.PREF_ENABLED_GLOBALLY, this);
Services.prefs.removeObserver(this.PREF_ENABLED_IN_PRIVATE_WINDOWS, this);
},
observe() {
this.updateEnabled();
},
get enabled() {
return this.enabledGlobally ||
(this.enabledInPrivateWindows &&
PrivateBrowsingUtils.isWindowPrivate(window));
},
enabledHistogramAdd(value) {
if (PrivateBrowsingUtils.isWindowPrivate(window)) {
return;
}
Services.telemetry.getHistogramById("TRACKING_PROTECTION_ENABLED").add(value);
},
disabledPBMHistogramAdd(value) {
if (PrivateBrowsingUtils.isWindowPrivate(window)) {
return;
}
Services.telemetry.getHistogramById("TRACKING_PROTECTION_PBM_DISABLED").add(value);
},
onGlobalToggleCommand() {
if (PrivateBrowsingUtils.isWindowPrivate(window)) {
Services.prefs.setBoolPref(this.PREF_ENABLED_IN_PRIVATE_WINDOWS, !this.enabledInPrivateWindows);
} else {
Services.prefs.setBoolPref(this.PREF_ENABLED_GLOBALLY, !this.enabledGlobally);
}
},
updateEnabled() {
this.enabledGlobally =
Services.prefs.getBoolPref(this.PREF_ENABLED_GLOBALLY);
this.enabledInPrivateWindows =
Services.prefs.getBoolPref(this.PREF_ENABLED_IN_PRIVATE_WINDOWS);
if (!ContentBlocking.contentBlockingUIEnabled) {
ContentBlocking.updateEnabled();
let appMenuButton = ContentBlocking.appMenuButton;
if (PrivateBrowsingUtils.isWindowPrivate(window)) {
appMenuButton.setAttribute("tooltiptext", this.enabledInPrivateWindows ?
this.strings.disableTooltipPB : this.strings.enableTooltipPB);
appMenuButton.setAttribute("enabled", this.enabledInPrivateWindows);
appMenuButton.setAttribute("aria-pressed", this.enabledInPrivateWindows);
} else {
appMenuButton.setAttribute("tooltiptext", this.enabledGlobally ?
this.strings.disableTooltip : this.strings.enableTooltip);
appMenuButton.setAttribute("enabled", this.enabledGlobally);
appMenuButton.setAttribute("aria-pressed", this.enabledGlobally);
}
}
},
};
var ContentBlocking = {
// If the user ignores the doorhanger, we stop showing it after some time.
MAX_INTROS: 20,
PREF_ENABLED: "browser.contentblocking.enabled",
PREF_UI_ENABLED: "browser.contentblocking.ui.enabled",
PREF_ANIMATIONS_ENABLED: "toolkit.cosmeticAnimations.enabled",
content: null, content: null,
icon: null, icon: null,
activeTooltipText: null, activeTooltipText: null,
disabledTooltipText: null, disabledTooltipText: null,
get appMenuLabel() {
delete this.appMenuLabel;
return this.appMenuLabel = document.getElementById("appMenu-tp-label");
},
get appMenuButton() {
delete this.appMenuButton;
return this.appMenuButton = document.getElementById("appMenu-tp-toggle");
},
strings: {
get enableTooltip() {
delete this.enableTooltip;
return this.enableTooltip =
gNavigatorBundle.getString("contentBlocking.toggle.enable.tooltip");
},
get disableTooltip() {
delete this.disableTooltip;
return this.disableTooltip =
gNavigatorBundle.getString("contentBlocking.toggle.disable.tooltip");
},
get appMenuTitle() {
delete this.appMenuTitle;
return this.appMenuTitle =
gNavigatorBundle.getString("contentBlocking.title");
},
get appMenuTooltip() {
delete this.appMenuTooltip;
return this.appMenuTooltip =
gNavigatorBundle.getString("contentBlocking.tooltip");
},
},
// A list of blockers that will be displayed in the categories list
// when blockable content is detected. A blocker must be an object
// with at least the following two properties:
// - enabled: Whether the blocker is currently turned on.
// - categoryItem: The DOM item that represents the entry in the category list.
//
// It may also contain an init() and uninit() function, which will be called
// on ContentBlocking.init() and ContentBlocking.uninit().
blockers: [FastBlock, TrackingProtection],
get _baseURIForChannelClassifier() { get _baseURIForChannelClassifier() {
// Convert document URI into the format used by // Convert document URI into the format used by
// nsChannelClassifier::ShouldEnableTrackingProtection. // nsChannelClassifier::ShouldEnableTrackingProtection.
@ -32,84 +198,82 @@ var TrackingProtection = {
init() { init() {
let $ = selector => document.querySelector(selector); let $ = selector => document.querySelector(selector);
this.container = $("#tracking-protection-container"); this.content = $("#identity-popup-content-blocking-content");
this.content = $("#tracking-protection-content");
this.icon = $("#tracking-protection-icon"); this.icon = $("#tracking-protection-icon");
this.appMenuContainer = $("#appMenu-tp-container");
this.appMenuSeparator = $("#appMenu-tp-separator");
this.iconBox = $("#tracking-protection-icon-box"); this.iconBox = $("#tracking-protection-icon-box");
this.animatedIcon = $("#tracking-protection-icon-animatable-image"); this.animatedIcon = $("#tracking-protection-icon-animatable-image");
this.animatedIcon.addEventListener("animationend", () => this.iconBox.removeAttribute("animate")); this.animatedIcon.addEventListener("animationend", () => this.iconBox.removeAttribute("animate"));
this.appMenuButton = $("#appMenu-tp-toggle");
this.enableTooltip =
gNavigatorBundle.getString("trackingProtection.toggle.enable.tooltip");
this.disableTooltip =
gNavigatorBundle.getString("trackingProtection.toggle.disable.tooltip");
this.enableTooltipPB =
gNavigatorBundle.getString("trackingProtection.toggle.enable.pbmode.tooltip");
this.disableTooltipPB =
gNavigatorBundle.getString("trackingProtection.toggle.disable.pbmode.tooltip");
this.updateAnimationsEnabled = () => { this.updateAnimationsEnabled = () => {
this.iconBox.toggleAttribute("animationsenabled", this.iconBox.toggleAttribute("animationsenabled",
Services.prefs.getBoolPref(this.PREF_ANIMATIONS_ENABLED, false)); Services.prefs.getBoolPref(this.PREF_ANIMATIONS_ENABLED, false));
}; };
for (let blocker of this.blockers) {
if (blocker.init) {
blocker.init();
}
}
this.updateAnimationsEnabled(); this.updateAnimationsEnabled();
Services.prefs.addObserver(this.PREF_ANIMATIONS_ENABLED, this.updateAnimationsEnabled); Services.prefs.addObserver(this.PREF_ANIMATIONS_ENABLED, this.updateAnimationsEnabled);
XPCOMUtils.defineLazyPreferenceGetter(this, "contentBlockingEnabled", this.PREF_ENABLED, false,
this.updateEnabled.bind(this));
XPCOMUtils.defineLazyPreferenceGetter(this, "contentBlockingUIEnabled", this.PREF_UI_ENABLED, false,
this.updateUIEnabled.bind(this));
this.updateEnabled(); this.updateEnabled();
this.updateUIEnabled();
this.updateAppMenuToggle = () => {
if (Services.prefs.getBoolPref(this.PREF_APP_MENU_TOGGLE, false)) {
this.appMenuContainer.removeAttribute("hidden");
this.appMenuSeparator.removeAttribute("hidden");
} else {
this.appMenuContainer.setAttribute("hidden", "true");
this.appMenuSeparator.setAttribute("hidden", "true");
}
};
Services.prefs.addObserver(this.PREF_ENABLED_GLOBALLY, this);
Services.prefs.addObserver(this.PREF_ENABLED_IN_PRIVATE_WINDOWS, this);
Services.prefs.addObserver(this.PREF_APP_MENU_TOGGLE, this.updateAppMenuToggle);
this.updateAppMenuToggle();
this.activeTooltipText = this.activeTooltipText =
gNavigatorBundle.getString("trackingProtection.icon.activeTooltip"); gNavigatorBundle.getString("trackingProtection.icon.activeTooltip");
this.disabledTooltipText = this.disabledTooltipText =
gNavigatorBundle.getString("trackingProtection.icon.disabledTooltip"); gNavigatorBundle.getString("trackingProtection.icon.disabledTooltip");
this.enabledHistogramAdd(this.enabledGlobally);
this.disabledPBMHistogramAdd(!this.enabledInPrivateWindows);
}, },
uninit() { uninit() {
Services.prefs.removeObserver(this.PREF_ENABLED_GLOBALLY, this); for (let blocker of this.blockers) {
Services.prefs.removeObserver(this.PREF_ENABLED_IN_PRIVATE_WINDOWS, this); if (blocker.uninit) {
Services.prefs.removeObserver(this.PREF_APP_MENU_TOGGLE, this.updateAppMenuToggle); blocker.uninit();
}
}
Services.prefs.removeObserver(this.PREF_ANIMATIONS_ENABLED, this.updateAnimationsEnabled); Services.prefs.removeObserver(this.PREF_ANIMATIONS_ENABLED, this.updateAnimationsEnabled);
}, },
observe() { get enabled() {
return this.contentBlockingUIEnabled ? this.contentBlockingEnabled : TrackingProtection.enabled;
},
updateEnabled() {
this.content.toggleAttribute("enabled", this.enabled);
if (this.contentBlockingUIEnabled) {
this.appMenuButton.setAttribute("tooltiptext", this.enabled ?
this.strings.disableTooltip : this.strings.enableTooltip);
this.appMenuButton.setAttribute("enabled", this.enabled);
this.appMenuButton.setAttribute("aria-pressed", this.enabled);
}
},
updateUIEnabled() {
this.content.toggleAttribute("contentBlockingUI", this.contentBlockingUIEnabled);
if (this.contentBlockingUIEnabled) {
this.appMenuLabel.setAttribute("label", this.strings.appMenuTitle);
this.appMenuLabel.setAttribute("tooltiptext", this.strings.appMenuTooltip);
}
this.updateEnabled(); this.updateEnabled();
}, },
get enabled() {
return this.enabledGlobally ||
(this.enabledInPrivateWindows &&
PrivateBrowsingUtils.isWindowPrivate(window));
},
onGlobalToggleCommand() { onGlobalToggleCommand() {
if (PrivateBrowsingUtils.isWindowPrivate(window)) { if (this.contentBlockingUIEnabled) {
Services.prefs.setBoolPref(this.PREF_ENABLED_IN_PRIVATE_WINDOWS, !this.enabledInPrivateWindows); Services.prefs.setBoolPref(this.PREF_ENABLED, !this.enabled);
} else { } else {
Services.prefs.setBoolPref(this.PREF_ENABLED_GLOBALLY, !this.enabledGlobally); TrackingProtection.onGlobalToggleCommand();
} }
}, },
@ -122,41 +286,6 @@ var TrackingProtection = {
openPreferences("privacy-trackingprotection", { origin }); openPreferences("privacy-trackingprotection", { origin });
}, },
updateEnabled() {
this.enabledGlobally =
Services.prefs.getBoolPref(this.PREF_ENABLED_GLOBALLY);
this.enabledInPrivateWindows =
Services.prefs.getBoolPref(this.PREF_ENABLED_IN_PRIVATE_WINDOWS);
this.content.setAttribute("enabled", this.enabled);
if (PrivateBrowsingUtils.isWindowPrivate(window)) {
this.appMenuButton.setAttribute("enabled", this.enabledInPrivateWindows);
this.appMenuButton.setAttribute("aria-pressed", this.enabledInPrivateWindows);
this.appMenuButton.setAttribute("tooltiptext", this.enabledInPrivateWindows ?
this.disableTooltipPB : this.enableTooltipPB);
} else {
this.appMenuButton.setAttribute("enabled", this.enabledGlobally);
this.appMenuButton.setAttribute("aria-pressed", this.enabledGlobally);
this.appMenuButton.setAttribute("tooltiptext", this.enabledGlobally ?
this.disableTooltip : this.enableTooltip);
}
},
enabledHistogramAdd(value) {
if (PrivateBrowsingUtils.isWindowPrivate(window)) {
return;
}
Services.telemetry.getHistogramById("TRACKING_PROTECTION_ENABLED").add(value);
},
disabledPBMHistogramAdd(value) {
if (PrivateBrowsingUtils.isWindowPrivate(window)) {
return;
}
Services.telemetry.getHistogramById("TRACKING_PROTECTION_PBM_DISABLED").add(value);
},
eventsHistogramAdd(value) { eventsHistogramAdd(value) {
if (PrivateBrowsingUtils.isWindowPrivate(window)) { if (PrivateBrowsingUtils.isWindowPrivate(window)) {
return; return;
@ -185,7 +314,8 @@ var TrackingProtection = {
// Don't deal with about:, file: etc. // Don't deal with about:, file: etc.
if (!baseURI) { if (!baseURI) {
this.cancelAnimation(); this.cancelAnimation();
this.iconBox.removeAttribute("state"); this.iconBox.removeAttribute("active");
this.iconBox.removeAttribute("hasException");
return; return;
} }
@ -198,6 +328,18 @@ var TrackingProtection = {
let isBlocking = state & Ci.nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT; let isBlocking = state & Ci.nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT;
let isAllowing = state & Ci.nsIWebProgressListener.STATE_LOADED_TRACKING_CONTENT; let isAllowing = state & Ci.nsIWebProgressListener.STATE_LOADED_TRACKING_CONTENT;
let detected = isBlocking || isAllowing;
// We consider the shield state as "active" when any kind of blocking-related
// activity occurs on the page (blocking or allowing). Since we have several
// content blockers, we need to go through them individually to figure out which
// ones are actually turned on or off.
// This state will be overriden later if there's an exception set for this site.
let active = this.enabled && detected;
for (let blocker of this.blockers) {
blocker.categoryItem.classList.toggle("blocked", this.enabled && blocker.enabled);
}
// Check whether the user has added an exception for this site. // Check whether the user has added an exception for this site.
let hasException = false; let hasException = false;
@ -208,62 +350,36 @@ var TrackingProtection = {
"trackingprotection") == Services.perms.ALLOW_ACTION; "trackingprotection") == Services.perms.ALLOW_ACTION;
} }
if (hasException) { this.content.toggleAttribute("detected", detected);
this.iconBox.setAttribute("hasException", "true"); this.content.toggleAttribute("hasException", hasException);
this.content.setAttribute("hasException", "true");
} else {
this.iconBox.removeAttribute("hasException");
this.content.removeAttribute("hasException");
}
if (isBlocking && this.enabled) { this.iconBox.toggleAttribute("active", active);
if (isSimulated) { this.iconBox.toggleAttribute("hasException", this.enabled && hasException);
this.cancelAnimation();
} else if (webProgress.isTopLevel) {
this.iconBox.setAttribute("animate", "true");
}
this.iconBox.setAttribute("tooltiptext", this.activeTooltipText); if (isSimulated) {
this.iconBox.setAttribute("state", "blocked-tracking-content"); this.cancelAnimation();
this.content.setAttribute("state", "blocked-tracking-content"); } else if (active && webProgress.isTopLevel) {
this.iconBox.setAttribute("animate", "true");
// Open the tracking protection introduction panel, if applicable. // Open the tracking protection introduction panel, if applicable.
if (this.enabledGlobally) { if (TrackingProtection.enabledGlobally) {
let introCount = Services.prefs.getIntPref("privacy.trackingprotection.introCount"); let introCount = Services.prefs.getIntPref("privacy.trackingprotection.introCount");
if (introCount < TrackingProtection.MAX_INTROS) { if (introCount < this.MAX_INTROS) {
Services.prefs.setIntPref("privacy.trackingprotection.introCount", ++introCount); Services.prefs.setIntPref("privacy.trackingprotection.introCount", ++introCount);
Services.prefs.savePrefFile(null); Services.prefs.savePrefFile(null);
this.showIntroPanel(); this.showIntroPanel();
} }
} }
}
if (hasException) {
this.iconBox.setAttribute("tooltiptext", this.disabledTooltipText);
this.shieldHistogramAdd(1);
} else if (active) {
this.iconBox.setAttribute("tooltiptext", this.activeTooltipText);
this.shieldHistogramAdd(2); this.shieldHistogramAdd(2);
} else if (isAllowing) {
if (isSimulated) {
this.cancelAnimation();
} else if (webProgress.isTopLevel) {
this.iconBox.setAttribute("animate", "true");
}
// Only show the shield when TP is enabled for now.
if (this.enabled) {
this.iconBox.setAttribute("tooltiptext", this.disabledTooltipText);
this.iconBox.setAttribute("state", "loaded-tracking-content");
this.shieldHistogramAdd(1);
} else {
this.iconBox.removeAttribute("tooltiptext");
this.iconBox.removeAttribute("state");
this.shieldHistogramAdd(0);
}
// Warn in the control center even with TP disabled.
this.content.setAttribute("state", "loaded-tracking-content");
} else { } else {
this.iconBox.removeAttribute("tooltiptext"); this.iconBox.removeAttribute("tooltiptext");
this.iconBox.removeAttribute("state");
this.content.removeAttribute("state");
// We didn't show the shield
this.shieldHistogramAdd(0); this.shieldHistogramAdd(0);
} }
@ -311,7 +427,7 @@ var TrackingProtection = {
dontShowIntroPanelAgain() { dontShowIntroPanelAgain() {
// This function may be called in private windows, but it does not change // This function may be called in private windows, but it does not change
// any preference unless Tracking Protection is enabled globally. // any preference unless Tracking Protection is enabled globally.
if (this.enabledGlobally) { if (TrackingProtection.enabledGlobally) {
Services.prefs.setIntPref("privacy.trackingprotection.introCount", Services.prefs.setIntPref("privacy.trackingprotection.introCount",
this.MAX_INTROS); this.MAX_INTROS);
Services.prefs.savePrefFile(null); Services.prefs.savePrefFile(null);

View file

@ -1313,7 +1313,7 @@ var gBrowserInit = {
LanguageDetectionListener.init(); LanguageDetectionListener.init();
BrowserOnClick.init(); BrowserOnClick.init();
FeedHandler.init(); FeedHandler.init();
TrackingProtection.init(); ContentBlocking.init();
CaptivePortalWatcher.init(); CaptivePortalWatcher.init();
ZoomUI.init(window); ZoomUI.init(window);
@ -1874,7 +1874,7 @@ var gBrowserInit = {
FeedHandler.uninit(); FeedHandler.uninit();
TrackingProtection.uninit(); ContentBlocking.uninit();
CaptivePortalWatcher.uninit(); CaptivePortalWatcher.uninit();
@ -4864,7 +4864,7 @@ var XULBrowserWindow = {
uri = Services.uriFixup.createExposableURI(uri); uri = Services.uriFixup.createExposableURI(uri);
} catch (e) {} } catch (e) {}
gIdentityHandler.updateIdentity(this._state, uri); gIdentityHandler.updateIdentity(this._state, uri);
TrackingProtection.onSecurityChange(this._state, aWebProgress, aIsSimulated); ContentBlocking.onSecurityChange(this._state, aWebProgress, aIsSimulated);
}, },
// simulate all change notifications after switching tabs // simulate all change notifications after switching tabs

View file

@ -15,6 +15,7 @@ for (let script of [
"chrome://browser/content/browser-captivePortal.js", "chrome://browser/content/browser-captivePortal.js",
"chrome://browser/content/browser-compacttheme.js", "chrome://browser/content/browser-compacttheme.js",
"chrome://browser/content/browser-contentblocking.js",
"chrome://browser/content/browser-feeds.js", "chrome://browser/content/browser-feeds.js",
"chrome://browser/content/browser-media.js", "chrome://browser/content/browser-media.js",
"chrome://browser/content/browser-pageActions.js", "chrome://browser/content/browser-pageActions.js",
@ -23,7 +24,6 @@ for (let script of [
"chrome://browser/content/browser-sidebar.js", "chrome://browser/content/browser-sidebar.js",
"chrome://browser/content/browser-siteIdentity.js", "chrome://browser/content/browser-siteIdentity.js",
"chrome://browser/content/browser-tabsintitlebar.js", "chrome://browser/content/browser-tabsintitlebar.js",
"chrome://browser/content/browser-trackingprotection.js",
"chrome://global/content/globalOverlay.js", "chrome://global/content/globalOverlay.js",
"chrome://browser/content/utilityOverlay.js", "chrome://browser/content/utilityOverlay.js",

View file

@ -440,32 +440,6 @@ support-files =
[browser_testOpenNewRemoteTabsFromNonRemoteBrowsers.js] [browser_testOpenNewRemoteTabsFromNonRemoteBrowsers.js]
run-if = e10s run-if = e10s
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD. # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_trackingUI_3.js]
tags = trackingprotection
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_trackingUI_4.js]
tags = trackingprotection
support-files =
trackingPage.html
benignPage.html
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_trackingUI_5.js]
tags = trackingprotection
support-files =
trackingPage.html
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_trackingUI_6.js]
tags = trackingprotection
support-files =
file_trackingUI_6.html
file_trackingUI_6.js
file_trackingUI_6.js^headers^
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_trackingUI_telemetry.js]
tags = trackingprotection
support-files =
trackingPage.html
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_typeAheadFind.js] [browser_typeAheadFind.js]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD. # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_unknownContentType_title.js] [browser_unknownContentType_title.js]

View file

@ -1,108 +0,0 @@
/*
* Test that the Tracking Protection icon is properly animated in the identity
* block when loading tabs and switching between tabs.
* See also Bug 1175858.
*/
const PREF = "privacy.trackingprotection.enabled";
const PB_PREF = "privacy.trackingprotection.pbmode.enabled";
const BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/benignPage.html";
const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/trackingPage.html";
var TrackingProtection = null;
var tabbrowser = null;
var {UrlClassifierTestUtils} = ChromeUtils.import("resource://testing-common/UrlClassifierTestUtils.jsm", {});
registerCleanupFunction(function() {
TrackingProtection = tabbrowser = null;
UrlClassifierTestUtils.cleanupTestTrackers();
Services.prefs.clearUserPref(PREF);
Services.prefs.clearUserPref(PB_PREF);
while (gBrowser.tabs.length > 1) {
gBrowser.removeCurrentTab();
}
});
function waitForSecurityChange(numChanges = 1) {
return new Promise(resolve => {
let n = 0;
let listener = {
onSecurityChange() {
n = n + 1;
info("Received onSecurityChange event " + n + " of " + numChanges);
if (n >= numChanges) {
tabbrowser.removeProgressListener(listener);
resolve();
}
}
};
tabbrowser.addProgressListener(listener);
});
}
async function testTrackingProtectionAnimation() {
info("Load a test page not containing tracking elements");
let benignTab = await BrowserTestUtils.openNewForegroundTab(tabbrowser, BENIGN_PAGE);
ok(!TrackingProtection.iconBox.hasAttribute("state"), "iconBox: no state");
ok(!TrackingProtection.iconBox.hasAttribute("animate"), "iconBox: no animate");
info("Load a test page containing tracking elements");
let trackingTab = await BrowserTestUtils.openNewForegroundTab(tabbrowser, TRACKING_PAGE);
ok(TrackingProtection.iconBox.hasAttribute("state"), "iconBox: state");
ok(TrackingProtection.iconBox.hasAttribute("animate"), "iconBox: animate");
info("Switch from tracking -> benign tab");
let securityChanged = waitForSecurityChange();
tabbrowser.selectedTab = benignTab;
await securityChanged;
ok(!TrackingProtection.iconBox.hasAttribute("state"), "iconBox: no state");
ok(!TrackingProtection.iconBox.hasAttribute("animate"), "iconBox: no animate");
info("Switch from benign -> tracking tab");
securityChanged = waitForSecurityChange();
tabbrowser.selectedTab = trackingTab;
await securityChanged;
ok(TrackingProtection.iconBox.hasAttribute("state"), "iconBox: state");
ok(!TrackingProtection.iconBox.hasAttribute("animate"), "iconBox: no animate");
info("Reload tracking tab");
securityChanged = waitForSecurityChange(2);
tabbrowser.reload();
await securityChanged;
ok(TrackingProtection.iconBox.hasAttribute("state"), "iconBox: state");
ok(TrackingProtection.iconBox.hasAttribute("animate"), "iconBox: animate");
}
add_task(async function testNormalBrowsing() {
await UrlClassifierTestUtils.addTestTrackers();
tabbrowser = gBrowser;
TrackingProtection = gBrowser.ownerGlobal.TrackingProtection;
ok(TrackingProtection, "TP is attached to the browser window");
Services.prefs.setBoolPref(PREF, true);
ok(TrackingProtection.enabled, "TP is enabled after setting the pref");
await testTrackingProtectionAnimation();
});
add_task(async function testPrivateBrowsing() {
let privateWin = await promiseOpenAndLoadWindow({private: true}, true);
tabbrowser = privateWin.gBrowser;
TrackingProtection = tabbrowser.ownerGlobal.TrackingProtection;
ok(TrackingProtection, "TP is attached to the private window");
Services.prefs.setBoolPref(PB_PREF, true);
ok(TrackingProtection.enabled, "TP is enabled after setting the pref");
await testTrackingProtectionAnimation();
privateWin.close();
});

View file

@ -1,132 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that sites added to the Tracking Protection whitelist in private
// browsing mode don't persist once the private browsing window closes.
const PB_PREF = "privacy.trackingprotection.pbmode.enabled";
const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/trackingPage.html";
var TrackingProtection = null;
var browser = null;
var {UrlClassifierTestUtils} = ChromeUtils.import("resource://testing-common/UrlClassifierTestUtils.jsm", {});
registerCleanupFunction(function() {
TrackingProtection = browser = null;
UrlClassifierTestUtils.cleanupTestTrackers();
});
function hidden(sel) {
let win = browser.ownerGlobal;
let el = win.document.querySelector(sel);
let display = win.getComputedStyle(el).getPropertyValue("display", null);
return display === "none";
}
function identityPopupState() {
let win = browser.ownerGlobal;
return win.document.getElementById("identity-popup").state;
}
function clickButton(sel) {
let win = browser.ownerGlobal;
let el = win.document.querySelector(sel);
el.doCommand();
}
function testTrackingPage(window) {
info("Tracking content must be blocked");
ok(!TrackingProtection.container.hidden, "The container is visible");
is(TrackingProtection.content.getAttribute("state"), "blocked-tracking-content",
'content: state="blocked-tracking-content"');
is(TrackingProtection.iconBox.getAttribute("state"), "blocked-tracking-content",
'iconBox: state="blocked-tracking-content"');
ok(!hidden("#tracking-protection-icon-box"), "icon box is visible");
ok(hidden("#tracking-action-block"), "blockButton is hidden");
ok(hidden("#tracking-action-unblock"), "unblockButton is hidden");
ok(!hidden("#tracking-action-unblock-private"), "unblockButtonPrivate is visible");
// Make sure that the blocked tracking elements message appears
ok(hidden("#tracking-not-detected"), "labelNoTracking is hidden");
ok(hidden("#tracking-loaded"), "labelTrackingLoaded is hidden");
ok(hidden("#tracking-loaded-exception"), "labelTrackingLoadedException is hidden");
ok(!hidden("#tracking-blocked"), "labelTrackingBlocked is visible");
}
function testTrackingPageUnblocked() {
info("Tracking content must be white-listed and not blocked");
ok(!TrackingProtection.container.hidden, "The container is visible");
is(TrackingProtection.content.getAttribute("state"), "loaded-tracking-content",
'content: state="loaded-tracking-content"');
is(TrackingProtection.iconBox.getAttribute("state"), "loaded-tracking-content",
'iconBox: state="loaded-tracking-content"');
ok(!hidden("#tracking-protection-icon-box"), "icon box is visible");
ok(!hidden("#tracking-action-block"), "blockButton is visible");
ok(hidden("#tracking-action-unblock"), "unblockButton is hidden");
// Make sure that the blocked tracking elements message appears
ok(hidden("#tracking-not-detected"), "labelNoTracking is hidden");
ok(!hidden("#tracking-loaded-exception"), "labelTrackingLoadedException is visible");
ok(hidden("#tracking-blocked"), "labelTrackingBlocked is hidden");
}
add_task(async function testExceptionAddition() {
await UrlClassifierTestUtils.addTestTrackers();
let privateWin = await promiseOpenAndLoadWindow({private: true}, true);
browser = privateWin.gBrowser;
let tab = await BrowserTestUtils.openNewForegroundTab({ gBrowser: browser, waitForLoad: true, waitForStateStop: true });
TrackingProtection = browser.ownerGlobal.TrackingProtection;
await pushPrefs([PB_PREF, true]);
ok(TrackingProtection.enabled, "TP is enabled after setting the pref");
info("Load a test page containing tracking elements");
await promiseTabLoadEvent(tab, TRACKING_PAGE);
testTrackingPage(tab.ownerGlobal);
info("Disable TP for the page (which reloads the page)");
let tabReloadPromise = promiseTabLoadEvent(tab);
clickButton("#tracking-action-unblock");
is(identityPopupState(), "closed", "foobar");
await tabReloadPromise;
testTrackingPageUnblocked();
info("Test that the exception is remembered across tabs in the same private window");
tab = browser.selectedTab = BrowserTestUtils.addTab(browser);
info("Load a test page containing tracking elements");
await promiseTabLoadEvent(tab, TRACKING_PAGE);
testTrackingPageUnblocked();
await promiseWindowClosed(privateWin);
});
add_task(async function testExceptionPersistence() {
info("Open another private browsing window");
let privateWin = await promiseOpenAndLoadWindow({private: true}, true);
browser = privateWin.gBrowser;
let tab = await BrowserTestUtils.openNewForegroundTab({ gBrowser: browser, waitForLoad: true, waitForStateStop: true });
TrackingProtection = browser.ownerGlobal.TrackingProtection;
ok(TrackingProtection.enabled, "TP is still enabled");
info("Load a test page containing tracking elements");
await promiseTabLoadEvent(tab, TRACKING_PAGE);
testTrackingPage(tab.ownerGlobal);
info("Disable TP for the page (which reloads the page)");
let tabReloadPromise = promiseTabLoadEvent(tab);
clickButton("#tracking-action-unblock");
is(identityPopupState(), "closed", "foobar");
await tabReloadPromise;
testTrackingPageUnblocked();
privateWin.close();
});

View file

@ -2,12 +2,20 @@
tags = trackingprotection tags = trackingprotection
support-files = support-files =
head.js head.js
../general/benignPage.html benignPage.html
../general/trackingPage.html trackingPage.html
[browser_trackingUI_3.js]
[browser_trackingUI_animation.js] [browser_trackingUI_animation.js]
[browser_trackingUI_animation_2.js]
[browser_trackingUI_appMenu.js] [browser_trackingUI_appMenu.js]
[browser_trackingUI_appMenu_toggle.js] [browser_trackingUI_appMenu_toggle.js]
[browser_trackingUI_fetch.js]
support-files =
file_trackingUI_fetch.html
file_trackingUI_fetch.js
file_trackingUI_fetch.js^headers^
[browser_trackingUI_open_preferences.js] [browser_trackingUI_open_preferences.js]
[browser_trackingUI_reload_hint.js] [browser_trackingUI_pbmode_exceptions.js]
[browser_trackingUI_state.js] [browser_trackingUI_state.js]
[browser_trackingUI_telemetry.js]

View file

@ -32,7 +32,7 @@ add_task(async function testNormalBrowsing() {
}); });
add_task(async function testPrivateBrowsing() { add_task(async function testPrivateBrowsing() {
let privateWin = await promiseOpenAndLoadWindow({private: true}, true); let privateWin = await BrowserTestUtils.openNewBrowserWindow({private: true});
let TrackingProtection = privateWin.gBrowser.ownerGlobal.TrackingProtection; let TrackingProtection = privateWin.gBrowser.ownerGlobal.TrackingProtection;
ok(TrackingProtection, "TP is attached to the browser window"); ok(TrackingProtection, "TP is attached to the browser window");

View file

@ -0,0 +1,113 @@
/*
* Test that the Content Blocking icon is properly animated in the identity
* block when loading tabs and switching between tabs.
* See also Bug 1175858.
*/
const CB_PREF = "browser.contentblocking.enabled";
const TP_PREF = "privacy.trackingprotection.enabled";
const TP_PB_PREF = "privacy.trackingprotection.enabled";
const BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/benignPage.html";
const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html";
registerCleanupFunction(function() {
UrlClassifierTestUtils.cleanupTestTrackers();
Services.prefs.clearUserPref(TP_PREF);
Services.prefs.clearUserPref(TP_PB_PREF);
Services.prefs.clearUserPref(CB_PREF);
});
function waitForSecurityChange(tabbrowser, numChanges = 1) {
return new Promise(resolve => {
let n = 0;
let listener = {
onSecurityChange() {
n = n + 1;
info("Received onSecurityChange event " + n + " of " + numChanges);
if (n >= numChanges) {
tabbrowser.removeProgressListener(listener);
resolve();
}
}
};
tabbrowser.addProgressListener(listener);
});
}
async function testTrackingProtectionAnimation(tabbrowser) {
info("Load a test page not containing tracking elements");
let benignTab = await BrowserTestUtils.openNewForegroundTab(tabbrowser, BENIGN_PAGE);
let ContentBlocking = tabbrowser.ownerGlobal.ContentBlocking;
ok(!ContentBlocking.iconBox.hasAttribute("active"), "iconBox not active");
ok(!ContentBlocking.iconBox.hasAttribute("animate"), "iconBox not animating");
info("Load a test page containing tracking elements");
let trackingTab = await BrowserTestUtils.openNewForegroundTab(tabbrowser, TRACKING_PAGE);
ok(ContentBlocking.iconBox.hasAttribute("active"), "iconBox active");
ok(ContentBlocking.iconBox.hasAttribute("animate"), "iconBox animating");
info("Switch from tracking -> benign tab");
let securityChanged = waitForSecurityChange(tabbrowser);
tabbrowser.selectedTab = benignTab;
await securityChanged;
ok(!ContentBlocking.iconBox.hasAttribute("active"), "iconBox not active");
ok(!ContentBlocking.iconBox.hasAttribute("animate"), "iconBox not animating");
info("Switch from benign -> tracking tab");
securityChanged = waitForSecurityChange(tabbrowser);
tabbrowser.selectedTab = trackingTab;
await securityChanged;
ok(ContentBlocking.iconBox.hasAttribute("active"), "iconBox active");
ok(!ContentBlocking.iconBox.hasAttribute("animate"), "iconBox not animating");
info("Reload tracking tab");
securityChanged = waitForSecurityChange(tabbrowser, 2);
tabbrowser.reload();
await securityChanged;
ok(ContentBlocking.iconBox.hasAttribute("active"), "iconBox active");
ok(ContentBlocking.iconBox.hasAttribute("animate"), "iconBox animating");
while (tabbrowser.tabs.length > 1) {
tabbrowser.removeCurrentTab();
}
}
add_task(async function testNormalBrowsing() {
await UrlClassifierTestUtils.addTestTrackers();
let ContentBlocking = gBrowser.ownerGlobal.ContentBlocking;
ok(ContentBlocking, "CB is attached to the browser window");
let TrackingProtection = gBrowser.ownerGlobal.TrackingProtection;
ok(TrackingProtection, "TP is attached to the browser window");
Services.prefs.setBoolPref(TP_PREF, true);
ok(TrackingProtection.enabled, "TP is enabled after setting the pref");
Services.prefs.setBoolPref(CB_PREF, true);
ok(ContentBlocking.enabled, "CB is enabled after setting the pref");
await testTrackingProtectionAnimation(gBrowser);
});
add_task(async function testPrivateBrowsing() {
let privateWin = await BrowserTestUtils.openNewBrowserWindow({private: true});
let tabbrowser = privateWin.gBrowser;
let ContentBlocking = tabbrowser.ownerGlobal.ContentBlocking;
ok(ContentBlocking, "CB is attached to the private window");
let TrackingProtection = tabbrowser.ownerGlobal.TrackingProtection;
ok(TrackingProtection, "TP is attached to the private window");
Services.prefs.setBoolPref(TP_PB_PREF, true);
ok(TrackingProtection.enabled, "TP is enabled after setting the pref");
Services.prefs.setBoolPref(CB_PREF, true);
ok(TrackingProtection.enabled, "CB is enabled after setting the pref");
await testTrackingProtectionAnimation(tabbrowser);
privateWin.close();
});

View file

@ -7,8 +7,6 @@ ChromeUtils.import("resource://testing-common/CustomizableUITestUtils.jsm", this
// Test that the "Tracking Protection" button in the app menu loads about:preferences // Test that the "Tracking Protection" button in the app menu loads about:preferences
add_task(async function testPreferencesButton() { add_task(async function testPreferencesButton() {
await SpecialPowers.pushPrefEnv({set: [["privacy.trackingprotection.appMenuToggle.enabled", true]]});
let cuiTestUtils = new CustomizableUITestUtils(window); let cuiTestUtils = new CustomizableUITestUtils(window);
await BrowserTestUtils.withNewTab(gBrowser, async function(browser) { await BrowserTestUtils.withNewTab(gBrowser, async function(browser) {

View file

@ -3,12 +3,47 @@
"use strict"; "use strict";
const CB_PREF = "browser.contentblocking.enabled";
const CB_UI_PREF = "browser.contentblocking.ui.enabled";
ChromeUtils.import("resource://testing-common/CustomizableUITestUtils.jsm", this); ChromeUtils.import("resource://testing-common/CustomizableUITestUtils.jsm", this);
// Test that the app menu toggle correctly flips the TP pref in // Test that the app menu toggle correctly flips the TP pref in
// normal windows and private windows. // normal windows and private windows.
add_task(async function testGlobalToggle() { add_task(async function testGlobalToggle() {
await SpecialPowers.pushPrefEnv({set: [["privacy.trackingprotection.appMenuToggle.enabled", true]]}); await SpecialPowers.pushPrefEnv({set: [[CB_UI_PREF, true]]});
let panelUIButton = await TestUtils.waitForCondition(() => document.getElementById("PanelUI-menu-button"));
info("Opening main menu");
let promiseShown = BrowserTestUtils.waitForEvent(PanelUI.mainView, "ViewShown");
panelUIButton.click();
await promiseShown;
info("Opened main menu");
let toggle = document.getElementById("appMenu-tp-toggle");
Services.prefs.setBoolPref(CB_PREF, false);
await TestUtils.waitForCondition(() => toggle.getAttribute("enabled") == "false");
Services.prefs.setBoolPref(CB_PREF, true);
await TestUtils.waitForCondition(() => toggle.getAttribute("enabled") == "true");
toggle.click();
is(Services.prefs.getBoolPref(CB_PREF), false);
toggle.click();
is(Services.prefs.getBoolPref(CB_PREF), true);
Services.prefs.clearUserPref(CB_PREF);
});
// Test that the app menu toggle correctly flips the TP pref in
// normal windows and private windows.
add_task(async function testGlobalToggleTP() {
await SpecialPowers.pushPrefEnv({set: [[CB_UI_PREF, false]]});
async function runTest(privateWindow) { async function runTest(privateWindow) {
let win = await BrowserTestUtils.openNewBrowserWindow({private: privateWindow}); let win = await BrowserTestUtils.openNewBrowserWindow({private: privateWindow});

View file

@ -1,4 +1,4 @@
const URL = "http://mochi.test:8888/browser/browser/base/content/test/general/file_trackingUI_6.html"; const URL = "http://mochi.test:8888/browser/browser/base/content/test/trackingUI/file_trackingUI_fetch.html";
function waitForSecurityChange(numChanges = 1) { function waitForSecurityChange(numChanges = 1) {
return new Promise(resolve => { return new Promise(resolve => {
@ -18,7 +18,10 @@ function waitForSecurityChange(numChanges = 1) {
} }
add_task(async function test_fetch() { add_task(async function test_fetch() {
await SpecialPowers.pushPrefEnv({ set: [["privacy.trackingprotection.enabled", true]] }); await SpecialPowers.pushPrefEnv({ set: [
["privacy.trackingprotection.enabled", true],
["browser.contentblocking.enabled", true],
]});
await BrowserTestUtils.withNewTab({ gBrowser, url: URL }, async function(newTabBrowser) { await BrowserTestUtils.withNewTab({ gBrowser, url: URL }, async function(newTabBrowser) {
let securityChange = waitForSecurityChange(); let securityChange = waitForSecurityChange();
@ -29,15 +32,13 @@ add_task(async function test_fetch() {
}); });
await securityChange; await securityChange;
var TrackingProtection = newTabBrowser.ownerGlobal.TrackingProtection; let ContentBlocking = newTabBrowser.ownerGlobal.ContentBlocking;
ok(TrackingProtection, "got TP object"); ok(ContentBlocking, "got CB object");
ok(TrackingProtection.enabled, "TP is enabled"); ok(ContentBlocking.enabled, "CB is enabled");
is(TrackingProtection.content.getAttribute("state"), "blocked-tracking-content", ok(ContentBlocking.content.hasAttribute("detected"), "has detected content blocking");
'content: state="blocked-tracking-content"'); ok(ContentBlocking.iconBox.hasAttribute("active"), "icon box is active");
is(TrackingProtection.iconBox.getAttribute("state"), "blocked-tracking-content", is(ContentBlocking.iconBox.getAttribute("tooltiptext"),
'iconBox: state="blocked-tracking-content"');
is(TrackingProtection.iconBox.getAttribute("tooltiptext"),
gNavigatorBundle.getString("trackingProtection.icon.activeTooltip"), "correct tooltip"); gNavigatorBundle.getString("trackingProtection.icon.activeTooltip"), "correct tooltip");
}); });
}); });

View file

@ -3,7 +3,10 @@
"use strict"; "use strict";
const PREF = "privacy.trackingprotection.enabled"; const CB_PREF = "browser.contentblocking.enabled";
const CB_UI_PREF = "browser.contentblocking.ui.enabled";
const TP_PREF = "privacy.trackingprotection.enabled";
const FB_PREF = "browser.fastblock.enabled";
const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html"; const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html";
async function waitAndAssertPreferencesShown() { async function waitAndAssertPreferencesShown() {
@ -44,6 +47,32 @@ add_task(async function testOpenPreferencesFromPrefsButton() {
}); });
}); });
// Tests that clicking the contentblocking category items "add blocking" labels
// links to about:preferences
add_task(async function testOpenPreferencesFromAddBlockingButtons() {
SpecialPowers.pushPrefEnv({set: [
[CB_PREF, true],
[CB_UI_PREF, true],
[FB_PREF, false],
[TP_PREF, false],
]});
await BrowserTestUtils.withNewTab(TRACKING_PAGE, async function() {
let addBlockingButtons = document.querySelectorAll(".identity-popup-content-blocking-category-add-blocking");
for (let button of addBlockingButtons) {
let promisePanelOpen = BrowserTestUtils.waitForEvent(gIdentityHandler._identityPopup, "popupshown");
gIdentityHandler._identityBox.click();
await promisePanelOpen;
ok(BrowserTestUtils.is_visible(button), "Button is shown.");
let shown = waitAndAssertPreferencesShown();
button.click();
await shown;
}
});
});
add_task(async function cleanup() { add_task(async function cleanup() {
UrlClassifierTestUtils.cleanupTestTrackers(); UrlClassifierTestUtils.cleanupTestTrackers();
}); });

View file

@ -0,0 +1,162 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that sites added to the Tracking Protection whitelist in private
// browsing mode don't persist once the private browsing window closes.
const CB_PREF = "browser.contentblocking.enabled";
const TP_PB_PREF = "privacy.trackingprotection.enabled";
const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html";
var TrackingProtection = null;
var ContentBlocking = null;
var browser = null;
registerCleanupFunction(function() {
Services.prefs.clearUserPref(TP_PB_PREF);
Services.prefs.clearUserPref(CB_PREF);
ContentBlocking = TrackingProtection = browser = null;
UrlClassifierTestUtils.cleanupTestTrackers();
});
function hidden(sel) {
let win = browser.ownerGlobal;
let el = win.document.querySelector(sel);
let display = win.getComputedStyle(el).getPropertyValue("display", null);
return display === "none";
}
function identityPopupState() {
let win = browser.ownerGlobal;
return win.document.getElementById("identity-popup").state;
}
function clickButton(sel) {
let win = browser.ownerGlobal;
let el = win.document.querySelector(sel);
el.doCommand();
}
function testTrackingPage(window) {
info("Tracking content must be blocked");
ok(ContentBlocking.content.hasAttribute("detected"), "trackers are detected");
ok(!ContentBlocking.content.hasAttribute("hasException"), "content shows no exception");
ok(BrowserTestUtils.is_visible(ContentBlocking.iconBox), "icon box is visible");
ok(ContentBlocking.iconBox.hasAttribute("active"), "shield is active");
ok(!ContentBlocking.iconBox.hasAttribute("hasException"), "icon box shows no exception");
is(ContentBlocking.iconBox.getAttribute("tooltiptext"),
gNavigatorBundle.getString("trackingProtection.icon.activeTooltip"), "correct tooltip");
ok(hidden("#tracking-action-block"), "blockButton is hidden");
if (PrivateBrowsingUtils.isWindowPrivate(window)) {
ok(hidden("#tracking-action-unblock"), "unblockButton is hidden");
ok(!hidden("#tracking-action-unblock-private"), "unblockButtonPrivate is visible");
} else {
ok(!hidden("#tracking-action-unblock"), "unblockButton is visible");
ok(hidden("#tracking-action-unblock-private"), "unblockButtonPrivate is hidden");
}
ok(hidden("#identity-popup-content-blocking-not-detected"), "blocking not detected label is hidden");
ok(!hidden("#identity-popup-content-blocking-detected"), "blocking detected label is visible");
ok(!hidden("#identity-popup-content-blocking-category-list"), "category list is visible");
ok(hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-add-blocking"),
"TP category item is not showing add blocking");
ok(!hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-state-label"),
"TP category item is set to blocked");
}
function testTrackingPageUnblocked() {
info("Tracking content must be white-listed and not blocked");
ok(ContentBlocking.content.hasAttribute("detected"), "trackers are detected");
ok(ContentBlocking.content.hasAttribute("hasException"), "content shows exception");
ok(ContentBlocking.iconBox.hasAttribute("active"), "shield is active");
ok(ContentBlocking.iconBox.hasAttribute("hasException"), "shield shows exception");
is(ContentBlocking.iconBox.getAttribute("tooltiptext"),
gNavigatorBundle.getString("trackingProtection.icon.disabledTooltip"), "correct tooltip");
ok(BrowserTestUtils.is_visible(ContentBlocking.iconBox), "icon box is visible");
ok(!hidden("#tracking-action-block"), "blockButton is visible");
ok(hidden("#tracking-action-unblock"), "unblockButton is hidden");
ok(!hidden("#identity-popup-content-blocking-disabled-label"), "disabled label is visible");
ok(hidden("#identity-popup-content-blocking-not-detected"), "blocking not detected label is hidden");
ok(!hidden("#identity-popup-content-blocking-detected"), "blocking detected label is visible");
ok(!hidden("#identity-popup-content-blocking-category-list"), "category list is visible");
ok(hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-add-blocking"),
"TP category item is not showing add blocking");
ok(hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-state-label"),
"TP category item is not set to blocked");
}
add_task(async function testExceptionAddition() {
await UrlClassifierTestUtils.addTestTrackers();
let privateWin = await BrowserTestUtils.openNewBrowserWindow({private: true});
browser = privateWin.gBrowser;
let tab = await BrowserTestUtils.openNewForegroundTab({ gBrowser: browser, waitForLoad: true, waitForStateStop: true });
ContentBlocking = browser.ownerGlobal.ContentBlocking;
ok(ContentBlocking, "CB is attached to the private window");
TrackingProtection = browser.ownerGlobal.TrackingProtection;
ok(TrackingProtection, "TP is attached to the private window");
Services.prefs.setBoolPref(TP_PB_PREF, true);
ok(TrackingProtection.enabled, "TP is enabled after setting the pref");
Services.prefs.setBoolPref(CB_PREF, true);
ok(TrackingProtection.enabled, "CB is enabled after setting the pref");
info("Load a test page containing tracking elements");
await promiseTabLoadEvent(tab, TRACKING_PAGE);
testTrackingPage(tab.ownerGlobal);
info("Disable TP for the page (which reloads the page)");
let tabReloadPromise = promiseTabLoadEvent(tab);
clickButton("#tracking-action-unblock");
is(identityPopupState(), "closed", "Identity popup is closed");
await tabReloadPromise;
testTrackingPageUnblocked();
info("Test that the exception is remembered across tabs in the same private window");
tab = browser.selectedTab = BrowserTestUtils.addTab(browser);
info("Load a test page containing tracking elements");
await promiseTabLoadEvent(tab, TRACKING_PAGE);
testTrackingPageUnblocked();
privateWin.close();
});
add_task(async function testExceptionPersistence() {
info("Open another private browsing window");
let privateWin = await BrowserTestUtils.openNewBrowserWindow({private: true});
browser = privateWin.gBrowser;
let tab = await BrowserTestUtils.openNewForegroundTab({ gBrowser: browser, waitForLoad: true, waitForStateStop: true });
ContentBlocking = browser.ownerGlobal.ContentBlocking;
ok(ContentBlocking, "CB is attached to the private window");
TrackingProtection = browser.ownerGlobal.TrackingProtection;
ok(TrackingProtection, "TP is attached to the private window");
ok(ContentBlocking.enabled, "CB is still enabled");
ok(TrackingProtection.enabled, "TP is still enabled");
info("Load a test page containing tracking elements");
await promiseTabLoadEvent(tab, TRACKING_PAGE);
testTrackingPage(tab.ownerGlobal);
info("Disable TP for the page (which reloads the page)");
let tabReloadPromise = promiseTabLoadEvent(tab);
clickButton("#tracking-action-unblock");
is(identityPopupState(), "closed", "Identity popup is closed");
await tabReloadPromise;
testTrackingPageUnblocked();
privateWin.close();
});

View file

@ -1,84 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const PREF = "privacy.trackingprotection.enabled";
const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html";
// TODO: replace this once bug 1428847 is done.
function hidden(el) {
let win = el.ownerGlobal;
let display = win.getComputedStyle(el).getPropertyValue("display", null);
let opacity = win.getComputedStyle(el).getPropertyValue("opacity", null);
return display === "none" || opacity === "0";
}
add_task(async function setup() {
await UrlClassifierTestUtils.addTestTrackers();
});
// Tests that we show the reload hint if the user enables TP on
// a site that has already loaded trackers before and that pressing
// the reload button reloads the page.
add_task(async function testReloadHint() {
Services.prefs.setBoolPref(PREF, false);
await BrowserTestUtils.withNewTab(TRACKING_PAGE, async function() {
let promisePanelOpen = BrowserTestUtils.waitForEvent(window.gIdentityHandler._identityPopup, "popupshown");
window.gIdentityHandler._identityBox.click();
await promisePanelOpen;
let blockButton = document.getElementById("tracking-action-block");
let reloadButton = document.getElementById("tracking-action-reload");
let trackingLoaded = document.getElementById("tracking-loaded");
let reloadHint = document.getElementById("tracking-reload-required");
ok(!hidden(trackingLoaded), "The tracking loaded info is shown.");
ok(hidden(blockButton), "The enable tracking protection button is not shown.");
ok(hidden(reloadButton), "The reload button is not shown.");
ok(hidden(reloadHint), "The reload hint is not shown.");
Services.prefs.setBoolPref(PREF, true);
ok(hidden(blockButton), "The enable tracking protection button is not shown.");
ok(hidden(trackingLoaded), "The tracking loaded info is not shown.");
ok(!hidden(reloadButton), "The reload button is shown.");
ok(!hidden(reloadHint), "The reload hint is shown.");
let reloaded = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, TRACKING_PAGE);
reloadButton.click();
await reloaded;
});
Services.prefs.clearUserPref(PREF);
});
// Tests that the reload hint does not appear on a non-tracking page.
add_task(async function testReloadHint() {
Services.prefs.setBoolPref(PREF, false);
await BrowserTestUtils.withNewTab("https://example.com", async function() {
let promisePanelOpen = BrowserTestUtils.waitForEvent(window.gIdentityHandler._identityPopup, "popupshown");
window.gIdentityHandler._identityBox.click();
await promisePanelOpen;
let trackingNotDetected = document.getElementById("tracking-not-detected");
let reloadButton = document.getElementById("tracking-action-reload");
let reloadHint = document.getElementById("tracking-reload-required");
ok(!hidden(trackingNotDetected), "The tracking not detected info is shown.");
ok(hidden(reloadButton), "The reload button is not shown.");
ok(hidden(reloadHint), "The reload hint is not shown.");
Services.prefs.setBoolPref(PREF, true);
ok(!hidden(trackingNotDetected), "The tracking not detected info is shown.");
ok(hidden(reloadButton), "The reload button is not shown.");
ok(hidden(reloadHint), "The reload hint is not shown.");
});
Services.prefs.clearUserPref(PREF);
});
add_task(async function cleanup() {
UrlClassifierTestUtils.cleanupTestTrackers();
});

View file

@ -14,21 +14,21 @@
* See also Bugs 1175327, 1043801, 1178985 * See also Bugs 1175327, 1043801, 1178985
*/ */
const PREF = "privacy.trackingprotection.enabled"; const CB_PREF = "browser.contentblocking.enabled";
const PB_PREF = "privacy.trackingprotection.pbmode.enabled"; const TP_PREF = "privacy.trackingprotection.enabled";
const TP_PB_PREF = "privacy.trackingprotection.enabled";
const BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/benignPage.html"; const BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/benignPage.html";
const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html"; const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html";
var ContentBlocking = null;
var TrackingProtection = null; var TrackingProtection = null;
var tabbrowser = null; var tabbrowser = null;
registerCleanupFunction(function() { registerCleanupFunction(function() {
TrackingProtection = tabbrowser = null; TrackingProtection = ContentBlocking = tabbrowser = null;
UrlClassifierTestUtils.cleanupTestTrackers(); UrlClassifierTestUtils.cleanupTestTrackers();
Services.prefs.clearUserPref(PREF); Services.prefs.clearUserPref(TP_PREF);
Services.prefs.clearUserPref(PB_PREF); Services.prefs.clearUserPref(TP_PB_PREF);
while (gBrowser.tabs.length > 1) { Services.prefs.clearUserPref(CB_PREF);
gBrowser.removeCurrentTab();
}
}); });
// This is a special version of "hidden" that doesn't check for item // This is a special version of "hidden" that doesn't check for item
@ -50,64 +50,61 @@ function clickButton(sel) {
function testBenignPage() { function testBenignPage() {
info("Non-tracking content must not be blocked"); info("Non-tracking content must not be blocked");
ok(!TrackingProtection.container.hidden, "The container is visible"); ok(!ContentBlocking.content.hasAttribute("detected"), "no trackers are detected");
ok(!TrackingProtection.content.hasAttribute("state"), "content: no state"); ok(!ContentBlocking.content.hasAttribute("hasException"), "content shows no exception");
ok(!TrackingProtection.iconBox.hasAttribute("state"), "icon box: no state");
ok(!TrackingProtection.iconBox.hasAttribute("tooltiptext"), "icon box: no tooltip");
let doc = tabbrowser.ownerGlobal.document; ok(!ContentBlocking.iconBox.hasAttribute("active"), "shield is not active");
ok(BrowserTestUtils.is_hidden(doc.getElementById("tracking-protection-icon-box")), "icon box is hidden"); ok(!ContentBlocking.iconBox.hasAttribute("hasException"), "icon box shows no exception");
ok(!ContentBlocking.iconBox.hasAttribute("tooltiptext"), "icon box has no tooltip");
ok(BrowserTestUtils.is_hidden(ContentBlocking.iconBox), "icon box is hidden");
ok(hidden("#tracking-action-block"), "blockButton is hidden"); ok(hidden("#tracking-action-block"), "blockButton is hidden");
ok(hidden("#tracking-action-unblock"), "unblockButton is hidden"); ok(hidden("#tracking-action-unblock"), "unblockButton is hidden");
ok(!hidden("#tracking-protection-preferences-button"), "preferences button is visible"); is(!hidden("#identity-popup-content-blocking-disabled-label"), !ContentBlocking.enabled,
"disabled label is visible if CB is off");
// Make sure that the no tracking elements message appears ok(!hidden("#identity-popup-content-blocking-not-detected"), "blocking not detected label is visible");
ok(!hidden("#tracking-not-detected"), "labelNoTracking is visible"); ok(hidden("#identity-popup-content-blocking-detected"), "blocking detected label is hidden");
ok(hidden("#tracking-loaded"), "labelTrackingLoaded is hidden");
ok(hidden("#tracking-blocked"), "labelTrackingBlocked is hidden"); ok(hidden("#identity-popup-content-blocking-category-list"), "category list is hidden");
} }
function testBenignPageWithException() { function testBenignPageWithException() {
info("Non-tracking content must not be blocked"); info("Non-tracking content must not be blocked");
ok(!TrackingProtection.container.hidden, "The container is visible"); ok(!ContentBlocking.content.hasAttribute("detected"), "no trackers are detected");
ok(!TrackingProtection.content.hasAttribute("state"), "content: no state"); ok(ContentBlocking.content.hasAttribute("hasException"), "content shows exception");
ok(TrackingProtection.content.hasAttribute("hasException"), "content has exception attribute");
ok(TrackingProtection.iconBox.hasAttribute("hasException"), "icon box has exception attribute");
ok(!TrackingProtection.iconBox.hasAttribute("state"), "icon box: no state");
ok(!TrackingProtection.iconBox.hasAttribute("tooltiptext"), "icon box: no tooltip");
let doc = tabbrowser.ownerGlobal.document; ok(!ContentBlocking.iconBox.hasAttribute("active"), "shield is not active");
ok(BrowserTestUtils.is_hidden(doc.getElementById("tracking-protection-icon-box")), "icon box is hidden"); is(ContentBlocking.iconBox.hasAttribute("hasException"), ContentBlocking.enabled,
is(!hidden("#tracking-action-block"), TrackingProtection.enabled, "shield shows exception if CB is on");
"blockButton is visible if TP is on"); is(ContentBlocking.iconBox.getAttribute("tooltiptext"),
gNavigatorBundle.getString("trackingProtection.icon.disabledTooltip"), "correct tooltip");
is(!BrowserTestUtils.is_hidden(ContentBlocking.iconBox), ContentBlocking.enabled,
"icon box is not hidden if CB is on");
is(!hidden("#tracking-action-block"), ContentBlocking.enabled,
"blockButton is visible if CB is on");
ok(hidden("#tracking-action-unblock"), "unblockButton is hidden"); ok(hidden("#tracking-action-unblock"), "unblockButton is hidden");
ok(!hidden("#tracking-protection-preferences-button"), "preferences button is visible"); ok(!hidden("#identity-popup-content-blocking-disabled-label"), "disabled label is visible");
is(!hidden("#tracking-not-detected-exception"), TrackingProtection.enabled, ok(!hidden("#identity-popup-content-blocking-not-detected"), "blocking not detected label is visible");
"labelNoTrackingException is visible if TP is on"); ok(hidden("#identity-popup-content-blocking-detected"), "blocking detected label is hidden");
is(hidden("#tracking-not-detected"), TrackingProtection.enabled,
"labelNoTracking is visible if TP is off"); ok(hidden("#identity-popup-content-blocking-category-list"), "category list is hidden");
ok(hidden("#tracking-loaded"), "labelTrackingLoaded is hidden");
ok(hidden("#tracking-blocked"), "labelTrackingBlocked is hidden");
} }
function testTrackingPage(window) { function testTrackingPage(window) {
info("Tracking content must be blocked"); info("Tracking content must be blocked");
ok(!TrackingProtection.container.hidden, "The container is visible"); ok(ContentBlocking.content.hasAttribute("detected"), "trackers are detected");
is(TrackingProtection.content.getAttribute("state"), "blocked-tracking-content", ok(!ContentBlocking.content.hasAttribute("hasException"), "content shows no exception");
'content: state="blocked-tracking-content"');
is(TrackingProtection.iconBox.getAttribute("state"), "blocked-tracking-content", ok(BrowserTestUtils.is_visible(ContentBlocking.iconBox), "icon box is visible");
'icon box: state="blocked-tracking-content"'); ok(ContentBlocking.iconBox.hasAttribute("active"), "shield is active");
is(TrackingProtection.iconBox.getAttribute("tooltiptext"), ok(!ContentBlocking.iconBox.hasAttribute("hasException"), "icon box shows no exception");
is(ContentBlocking.iconBox.getAttribute("tooltiptext"),
gNavigatorBundle.getString("trackingProtection.icon.activeTooltip"), "correct tooltip"); gNavigatorBundle.getString("trackingProtection.icon.activeTooltip"), "correct tooltip");
ok(!TrackingProtection.content.hasAttribute("hasException"), "content has no exception attribute");
ok(!TrackingProtection.iconBox.hasAttribute("hasException"), "icon box has no exception attribute");
let doc = tabbrowser.ownerGlobal.document;
ok(BrowserTestUtils.is_visible(doc.getElementById("tracking-protection-icon-box")), "icon box is visible");
ok(hidden("#tracking-action-block"), "blockButton is hidden"); ok(hidden("#tracking-action-block"), "blockButton is hidden");
ok(!hidden("#tracking-protection-preferences-button"), "preferences button is visible");
if (PrivateBrowsingUtils.isWindowPrivate(window)) { if (PrivateBrowsingUtils.isWindowPrivate(window)) {
ok(hidden("#tracking-action-unblock"), "unblockButton is hidden"); ok(hidden("#tracking-action-unblock"), "unblockButton is hidden");
@ -117,45 +114,66 @@ function testTrackingPage(window) {
ok(hidden("#tracking-action-unblock-private"), "unblockButtonPrivate is hidden"); ok(hidden("#tracking-action-unblock-private"), "unblockButtonPrivate is hidden");
} }
// Make sure that the blocked tracking elements message appears ok(hidden("#identity-popup-content-blocking-not-detected"), "blocking not detected label is hidden");
ok(hidden("#tracking-not-detected"), "labelNoTracking is hidden"); ok(!hidden("#identity-popup-content-blocking-detected"), "blocking detected label is visible");
ok(hidden("#tracking-loaded"), "labelTrackingLoaded is hidden");
ok(hidden("#tracking-loaded-exception"), "labelTrackingLoadedException is hidden"); ok(!hidden("#identity-popup-content-blocking-category-list"), "category list is visible");
ok(!hidden("#tracking-blocked"), "labelTrackingBlocked is visible"); ok(hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-add-blocking"),
"TP category item is not showing add blocking");
ok(!hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-state-label"),
"TP category item is set to blocked");
} }
function testTrackingPageUnblocked() { function testTrackingPageUnblocked() {
info("Tracking content must be white-listed and not blocked"); info("Tracking content must be white-listed and not blocked");
is(TrackingProtection.content.hasAttribute("hasException"), TrackingProtection.enabled, ok(ContentBlocking.content.hasAttribute("detected"), "trackers are detected");
"content has exception attribute if TP is on"); ok(ContentBlocking.content.hasAttribute("hasException"), "content shows exception");
is(TrackingProtection.iconBox.hasAttribute("hasException"), TrackingProtection.enabled,
"icon box has exception attribute if TP is on");
ok(!TrackingProtection.container.hidden, "The container is visible");
is(TrackingProtection.content.getAttribute("state"), "loaded-tracking-content",
'content: state="loaded-tracking-content"');
if (TrackingProtection.enabled) {
is(TrackingProtection.iconBox.getAttribute("state"), "loaded-tracking-content",
'icon box: state="loaded-tracking-content"');
is(TrackingProtection.iconBox.getAttribute("tooltiptext"),
gNavigatorBundle.getString("trackingProtection.icon.disabledTooltip"), "correct tooltip");
}
let doc = tabbrowser.ownerGlobal.document; ok(ContentBlocking.iconBox.hasAttribute("active"), "shield is active");
is(BrowserTestUtils.is_visible(doc.getElementById("tracking-protection-icon-box")), TrackingProtection.enabled, "icon box is visible if TP is on"); ok(ContentBlocking.iconBox.hasAttribute("hasException"), "shield shows exception");
is(!hidden("#tracking-action-block"), TrackingProtection.enabled, "blockButton is visible if TP is on"); is(ContentBlocking.iconBox.getAttribute("tooltiptext"),
gNavigatorBundle.getString("trackingProtection.icon.disabledTooltip"), "correct tooltip");
ok(BrowserTestUtils.is_visible(ContentBlocking.iconBox), "icon box is visible");
ok(!hidden("#tracking-action-block"), "blockButton is visible");
ok(hidden("#tracking-action-unblock"), "unblockButton is hidden"); ok(hidden("#tracking-action-unblock"), "unblockButton is hidden");
ok(!hidden("#tracking-protection-preferences-button"), "preferences button is visible"); ok(!hidden("#identity-popup-content-blocking-disabled-label"), "disabled label is visible");
// Make sure that the blocked tracking elements message appears ok(hidden("#identity-popup-content-blocking-not-detected"), "blocking not detected label is hidden");
ok(hidden("#tracking-not-detected"), "labelNoTracking is hidden"); ok(!hidden("#identity-popup-content-blocking-detected"), "blocking detected label is visible");
is(hidden("#tracking-loaded"), TrackingProtection.enabled,
"labelTrackingLoaded is visible if TP is off"); ok(!hidden("#identity-popup-content-blocking-category-list"), "category list is visible");
is(!hidden("#tracking-loaded-exception"), TrackingProtection.enabled, ok(hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-add-blocking"),
"labelTrackingLoadedException is visible if TP is on"); "TP category item is not showing add blocking");
ok(hidden("#tracking-blocked"), "labelTrackingBlocked is hidden"); ok(hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-state-label"),
"TP category item is not set to blocked");
} }
async function testTrackingProtectionEnabled(tab) { function testTrackingPageWithCBDisabled() {
info("Tracking content must be white-listed and not blocked");
ok(ContentBlocking.content.hasAttribute("detected"), "trackers are detected");
ok(!ContentBlocking.content.hasAttribute("hasException"), "content shows no exception");
ok(!ContentBlocking.iconBox.hasAttribute("active"), "shield is not active");
ok(!ContentBlocking.iconBox.hasAttribute("hasException"), "shield shows no exception");
ok(!ContentBlocking.iconBox.getAttribute("tooltiptext"), "icon box has no tooltip");
ok(BrowserTestUtils.is_hidden(ContentBlocking.iconBox), "icon box is hidden");
ok(hidden("#tracking-action-block"), "blockButton is hidden");
ok(hidden("#tracking-action-unblock"), "unblockButton is hidden");
ok(!hidden("#identity-popup-content-blocking-disabled-label"), "disabled label is visible");
ok(hidden("#identity-popup-content-blocking-not-detected"), "blocking not detected label is hidden");
ok(!hidden("#identity-popup-content-blocking-detected"), "blocking detected label is visible");
ok(!hidden("#identity-popup-content-blocking-category-list"), "category list is visible");
ok(!hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-add-blocking"),
"TP category item is showing add blocking");
ok(hidden("#identity-popup-content-blocking-category-tracking-protection > .identity-popup-content-blocking-category-state-label"),
"TP category item is not set to blocked");
}
async function testContentBlockingEnabled(tab) {
info("Testing with Tracking Protection ENABLED."); info("Testing with Tracking Protection ENABLED.");
info("Load a test page not containing tracking elements"); info("Load a test page not containing tracking elements");
@ -184,7 +202,7 @@ async function testTrackingProtectionEnabled(tab) {
await promiseTabLoadEvent(tab, TRACKING_PAGE); await promiseTabLoadEvent(tab, TRACKING_PAGE);
testTrackingPage(tab.ownerGlobal); testTrackingPage(tab.ownerGlobal);
info("Disable TP for the page (which reloads the page)"); info("Disable CB for the page (which reloads the page)");
let tabReloadPromise = promiseTabLoadEvent(tab); let tabReloadPromise = promiseTabLoadEvent(tab);
clickButton("#tracking-action-unblock"); clickButton("#tracking-action-unblock");
await tabReloadPromise; await tabReloadPromise;
@ -197,7 +215,7 @@ async function testTrackingProtectionEnabled(tab) {
testTrackingPage(tab.ownerGlobal); testTrackingPage(tab.ownerGlobal);
} }
async function testTrackingProtectionDisabled(tab) { async function testContentBlockingDisabled(tab) {
info("Testing with Tracking Protection DISABLED."); info("Testing with Tracking Protection DISABLED.");
info("Load a test page not containing tracking elements"); info("Load a test page not containing tracking elements");
@ -224,7 +242,7 @@ async function testTrackingProtectionDisabled(tab) {
info("Load a test page containing tracking elements"); info("Load a test page containing tracking elements");
await promiseTabLoadEvent(tab, TRACKING_PAGE); await promiseTabLoadEvent(tab, TRACKING_PAGE);
testTrackingPageUnblocked(); testTrackingPageWithCBDisabled();
} }
add_task(async function testNormalBrowsing() { add_task(async function testNormalBrowsing() {
@ -233,20 +251,26 @@ add_task(async function testNormalBrowsing() {
tabbrowser = gBrowser; tabbrowser = gBrowser;
let tab = tabbrowser.selectedTab = BrowserTestUtils.addTab(tabbrowser); let tab = tabbrowser.selectedTab = BrowserTestUtils.addTab(tabbrowser);
ContentBlocking = gBrowser.ownerGlobal.ContentBlocking;
ok(ContentBlocking, "CB is attached to the browser window");
TrackingProtection = gBrowser.ownerGlobal.TrackingProtection; TrackingProtection = gBrowser.ownerGlobal.TrackingProtection;
ok(TrackingProtection, "TP is attached to the browser window"); ok(TrackingProtection, "TP is attached to the browser window");
is(TrackingProtection.enabled, Services.prefs.getBoolPref(PREF), is(TrackingProtection.enabled, Services.prefs.getBoolPref(TP_PREF),
"TP.enabled is based on the original pref value"); "TP.enabled is based on the original pref value");
Services.prefs.setBoolPref(PREF, true); Services.prefs.setBoolPref(TP_PREF, true);
ok(TrackingProtection.enabled, "TP is enabled after setting the pref"); ok(TrackingProtection.enabled, "TP is enabled after setting the pref");
Services.prefs.setBoolPref(CB_PREF, true);
ok(ContentBlocking.enabled, "CB is enabled after setting the pref");
await testTrackingProtectionEnabled(tab); await testContentBlockingEnabled(tab);
Services.prefs.setBoolPref(PREF, false); Services.prefs.setBoolPref(CB_PREF, false);
ok(!TrackingProtection.enabled, "TP is disabled after setting the pref"); ok(!ContentBlocking.enabled, "CB is disabled after setting the pref");
await testTrackingProtectionDisabled(tab); await testContentBlockingDisabled(tab);
gBrowser.removeCurrentTab();
}); });
add_task(async function testPrivateBrowsing() { add_task(async function testPrivateBrowsing() {
@ -254,20 +278,24 @@ add_task(async function testPrivateBrowsing() {
tabbrowser = privateWin.gBrowser; tabbrowser = privateWin.gBrowser;
let tab = tabbrowser.selectedTab = BrowserTestUtils.addTab(tabbrowser); let tab = tabbrowser.selectedTab = BrowserTestUtils.addTab(tabbrowser);
ContentBlocking = tabbrowser.ownerGlobal.ContentBlocking;
ok(ContentBlocking, "CB is attached to the private window");
TrackingProtection = tabbrowser.ownerGlobal.TrackingProtection; TrackingProtection = tabbrowser.ownerGlobal.TrackingProtection;
ok(TrackingProtection, "TP is attached to the private window"); ok(TrackingProtection, "TP is attached to the private window");
is(TrackingProtection.enabled, Services.prefs.getBoolPref(PB_PREF), is(TrackingProtection.enabled, Services.prefs.getBoolPref(TP_PB_PREF),
"TP.enabled is based on the pb pref value"); "TP.enabled is based on the pb pref value");
Services.prefs.setBoolPref(PB_PREF, true); Services.prefs.setBoolPref(TP_PB_PREF, true);
ok(TrackingProtection.enabled, "TP is enabled after setting the pref"); ok(TrackingProtection.enabled, "TP is enabled after setting the pref");
Services.prefs.setBoolPref(CB_PREF, true);
ok(TrackingProtection.enabled, "CB is enabled after setting the pref");
await testTrackingProtectionEnabled(tab); await testContentBlockingEnabled(tab);
Services.prefs.setBoolPref(PB_PREF, false); Services.prefs.setBoolPref(CB_PREF, false);
ok(!TrackingProtection.enabled, "TP is disabled after setting the pref"); ok(!ContentBlocking.enabled, "CB is disabled after setting the pref");
await testTrackingProtectionDisabled(tab); await testContentBlockingDisabled(tab);
privateWin.close(); privateWin.close();
}); });

View file

@ -3,9 +3,8 @@
*/ */
const PREF = "privacy.trackingprotection.enabled"; const PREF = "privacy.trackingprotection.enabled";
const BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/benignPage.html"; const BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/benignPage.html";
const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/trackingPage.html"; const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html";
const {UrlClassifierTestUtils} = ChromeUtils.import("resource://testing-common/UrlClassifierTestUtils.jsm", {});
/** /**
* Enable local telemetry recording for the duration of the tests. * Enable local telemetry recording for the duration of the tests.
@ -52,8 +51,8 @@ add_task(async function setup() {
ok(!TrackingProtection.enabled, "TP is not enabled"); ok(!TrackingProtection.enabled, "TP is not enabled");
// Open a window with TP disabled to make sure 'enabled' is logged correctly. // Open a window with TP disabled to make sure 'enabled' is logged correctly.
let newWin = await promiseOpenAndLoadWindow({}, true); let newWin = await BrowserTestUtils.openNewBrowserWindow({});
await promiseWindowClosed(newWin); newWin.close();
is(getEnabledCounts()[0], 1, "TP was disabled once on start up"); is(getEnabledCounts()[0], 1, "TP was disabled once on start up");
is(getEnabledCounts()[1], 0, "TP was not enabled on start up"); is(getEnabledCounts()[1], 0, "TP was not enabled on start up");
@ -64,7 +63,7 @@ add_task(async function setup() {
add_task(async function testNewWindow() { add_task(async function testNewWindow() {
let newWin = await promiseOpenAndLoadWindow({}, true); let newWin = await BrowserTestUtils.openNewBrowserWindow({});
let tab = await BrowserTestUtils.openNewForegroundTab(newWin.gBrowser); let tab = await BrowserTestUtils.openNewForegroundTab(newWin.gBrowser);
let TrackingProtection = newWin.TrackingProtection; let TrackingProtection = newWin.TrackingProtection;
ok(TrackingProtection, "TP is attached to the browser window"); ok(TrackingProtection, "TP is attached to the browser window");
@ -111,7 +110,7 @@ add_task(async function testNewWindow() {
is(getEventCounts()[2], 1, "Enable actions"); is(getEventCounts()[2], 1, "Enable actions");
todo_is(getShieldCounts()[0], 1, "FIXME: TOTAL PAGE LOADS WITHOUT TRACKING IS DOUBLE COUNTING"); todo_is(getShieldCounts()[0], 1, "FIXME: TOTAL PAGE LOADS WITHOUT TRACKING IS DOUBLE COUNTING");
await promiseWindowClosed(newWin); newWin.close();
// Reset these to make counting easier for the next test // Reset these to make counting easier for the next test
getEventsHistogram().clear(); getEventsHistogram().clear();
@ -120,7 +119,7 @@ add_task(async function testNewWindow() {
}); });
add_task(async function testPrivateBrowsing() { add_task(async function testPrivateBrowsing() {
let privateWin = await promiseOpenAndLoadWindow({private: true}, true); let privateWin = await BrowserTestUtils.openNewBrowserWindow({private: true});
let tab = await BrowserTestUtils.openNewForegroundTab(privateWin.gBrowser); let tab = await BrowserTestUtils.openNewForegroundTab(privateWin.gBrowser);
let TrackingProtection = privateWin.TrackingProtection; let TrackingProtection = privateWin.TrackingProtection;
ok(TrackingProtection, "TP is attached to the browser window"); ok(TrackingProtection, "TP is attached to the browser window");
@ -140,5 +139,5 @@ add_task(async function testPrivateBrowsing() {
is(getEventCounts().reduce((p, c) => p + c), 0, "Telemetry logging off in PB mode"); is(getEventCounts().reduce((p, c) => p + c), 0, "Telemetry logging off in PB mode");
is(getShieldCounts().reduce((p, c) => p + c), 0, "Telemetry logging off in PB mode"); is(getShieldCounts().reduce((p, c) => p + c), 0, "Telemetry logging off in PB mode");
await promiseWindowClosed(privateWin); privateWin.close();
}); });

View file

@ -8,7 +8,7 @@
<p>Hello there!</p> <p>Hello there!</p>
<script type="application/javascript"> <script type="application/javascript">
function test_fetch() { function test_fetch() {
let url = "http://trackertest.org/browser/browser/base/content/test/general/file_trackingUI_6.js"; let url = "http://trackertest.org/browser/browser/base/content/test/trackingUI/file_trackingUI_fetch.js";
return fetch(url); return fetch(url);
} }
</script> </script>

View file

@ -36,6 +36,7 @@ browser.jar:
content/browser/browser-customization.js (content/browser-customization.js) content/browser/browser-customization.js (content/browser-customization.js)
content/browser/browser-data-submission-info-bar.js (content/browser-data-submission-info-bar.js) content/browser/browser-data-submission-info-bar.js (content/browser-data-submission-info-bar.js)
content/browser/browser-compacttheme.js (content/browser-compacttheme.js) content/browser/browser-compacttheme.js (content/browser-compacttheme.js)
content/browser/browser-contentblocking.js (content/browser-contentblocking.js)
#ifndef MOZILLA_OFFICIAL #ifndef MOZILLA_OFFICIAL
content/browser/browser-development-helpers.js (content/browser-development-helpers.js) content/browser/browser-development-helpers.js (content/browser-development-helpers.js)
#endif #endif
@ -53,7 +54,6 @@ browser.jar:
content/browser/browser-sync.js (content/browser-sync.js) content/browser/browser-sync.js (content/browser-sync.js)
content/browser/browser-tabsintitlebar.js (content/browser-tabsintitlebar.js) content/browser/browser-tabsintitlebar.js (content/browser-tabsintitlebar.js)
content/browser/browser-thumbnails.js (content/browser-thumbnails.js) content/browser/browser-thumbnails.js (content/browser-thumbnails.js)
content/browser/browser-trackingprotection.js (content/browser-trackingprotection.js)
content/browser/browser-webrender.js (content/browser-webrender.js) content/browser/browser-webrender.js (content/browser-webrender.js)
content/browser/tab-content.js (content/tab-content.js) content/browser/tab-content.js (content/tab-content.js)
content/browser/content.js (content/content.js) content/browser/content.js (content/content.js)

View file

@ -37,7 +37,7 @@ var AboutPrivateBrowsingHandler = {
} }
case "DontShowIntroPanelAgain": { case "DontShowIntroPanelAgain": {
let win = aMessage.target.browser.ownerGlobal; let win = aMessage.target.browser.ownerGlobal;
win.TrackingProtection.dontShowIntroPanelAgain(); win.ContentBlocking.dontShowIntroPanelAgain();
break; break;
} }
} }

View file

@ -51,53 +51,66 @@
<hbox id="tracking-protection-container" <hbox id="tracking-protection-container"
class="identity-popup-section" class="identity-popup-section"
when-connection="not-secure secure secure-ev secure-cert-user-overridden extension"> when-connection="not-secure secure secure-ev secure-cert-user-overridden extension">
<vbox id="tracking-protection-content" flex="1"> <vbox id="identity-popup-content-blocking-content" flex="1">
<hbox> <hbox>
<label id="tracking-protection-label-on" <label id="tracking-protection-label"
class="identity-popup-headline" class="identity-popup-headline"
flex="1">&trackingProtection.on;</label> flex="1">&trackingProtection.title;</label>
<label id="tracking-protection-label-off" <label id="content-blocking-label"
class="identity-popup-headline" class="identity-popup-headline"
flex="1">&trackingProtection.off;</label> flex="1">&contentBlocking.title;</label>
<hbox id="identity-popup-content-blocking-disabled-label">
<image/>
<label id="identity-popup-content-blocking-disabled-label-exception"
tooltiptext="&contentBlocking.exception.tooltip;">&contentBlocking.disabled.label;</label>
<label id="identity-popup-content-blocking-disabled-label-global"
tooltiptext="&contentBlocking.disabled.tooltip;">&contentBlocking.disabled.label;</label>
</hbox>
<toolbarbutton id="tracking-protection-preferences-button" <toolbarbutton id="tracking-protection-preferences-button"
class="identity-popup-preferences-button subviewbutton" class="identity-popup-preferences-button subviewbutton"
tooltiptext="&trackingProtection.tooltip;" tooltiptext="&trackingProtection.tooltip;"
oncommand="TrackingProtection.openPreferences('identityPopup-TP-preferencesButton');" /> oncommand="ContentBlocking.openPreferences('identityPopup-TP-preferencesButton');" />
</hbox> </hbox>
<description id="tracking-blocked" <description id="identity-popup-content-blocking-detected"
crop="end">&trackingProtection.detectedBlocked4;</description> crop="end">&contentBlocking.detected;</description>
<description id="tracking-loaded" <description id="identity-popup-content-blocking-not-detected"
crop="end">&trackingProtection.detectedNotBlocked5;</description> crop="end">&contentBlocking.notDetected;</description>
<description id="tracking-not-detected"
crop="end">&trackingProtection.notDetected5;</description> <vbox id="identity-popup-content-blocking-category-list">
<description id="tracking-loaded-exception" <hbox id="identity-popup-content-blocking-category-fastblock"
crop="end">&trackingProtection.detectedException;</description> class="identity-popup-content-blocking-category" align="center" role="group">
<description id="tracking-not-detected-exception" <image class="identity-popup-content-blocking-category-icon fastblock-icon"/>
crop="end">&trackingProtection.notDetectedException;</description> <label flex="1" class="identity-popup-content-blocking-category-label">&contentBlocking.fastBlock.label;</label>
<description id="tracking-reload-required" <label flex="1" class="identity-popup-content-blocking-category-state-label">&contentBlocking.fastBlock.blocked.label;</label>
crop="end">&trackingProtection.reloadRequired2;</description> <label flex="1" class="identity-popup-content-blocking-category-add-blocking text-link"
onclick="ContentBlocking.openPreferences('identityPopup-CB-fastblock');">&contentBlocking.fastBlock.add.label;</label>
</hbox>
<hbox id="identity-popup-content-blocking-category-tracking-protection"
class="identity-popup-content-blocking-category" align="center" role="group">
<image class="identity-popup-content-blocking-category-icon tracking-protection-icon"/>
<label flex="1" class="identity-popup-content-blocking-category-label">&contentBlocking.trackingProtection.label;</label>
<label flex="1" class="identity-popup-content-blocking-category-state-label">&contentBlocking.trackingProtection.blocked.label;</label>
<label flex="1" class="identity-popup-content-blocking-category-add-blocking text-link"
onclick="ContentBlocking.openPreferences('identityPopup-CB-tracking-protection');">&contentBlocking.trackingProtection.add.label;</label>
</hbox>
</vbox>
<button id="tracking-action-reload"
class="tracking-protection-button"
label="&trackingProtection.reload2.label;"
accesskey="&trackingProtection.reload2.accesskey;"
oncommand="TrackingProtection.hideIdentityPopupAndReload();" />
<button id="tracking-action-unblock" <button id="tracking-action-unblock"
class="tracking-protection-button" class="tracking-protection-button"
label="&trackingProtection.unblock3.label;" label="&trackingProtection.unblock4.label;"
accesskey="&trackingProtection.unblock3.accesskey;" accesskey="&trackingProtection.unblock4.accesskey;"
oncommand="TrackingProtection.disableForCurrentPage();" /> oncommand="ContentBlocking.disableForCurrentPage();" />
<button id="tracking-action-unblock-private" <button id="tracking-action-unblock-private"
class="tracking-protection-button" class="tracking-protection-button"
label="&trackingProtection.unblockPrivate3.label;" label="&trackingProtection.unblockPrivate4.label;"
accesskey="&trackingProtection.unblockPrivate3.accesskey;" accesskey="&trackingProtection.unblockPrivate4.accesskey;"
oncommand="TrackingProtection.disableForCurrentPage();" /> oncommand="ContentBlocking.disableForCurrentPage();" />
<button id="tracking-action-block" <button id="tracking-action-block"
class="tracking-protection-button" class="tracking-protection-button"
label="&trackingProtection.block4.label;" label="&trackingProtection.block5.label;"
accesskey="&trackingProtection.block4.accesskey;" accesskey="&trackingProtection.block5.accesskey;"
oncommand="TrackingProtection.enableForCurrentPage();" /> oncommand="ContentBlocking.enableForCurrentPage();" />
</vbox> </vbox>
</hbox> </hbox>

View file

@ -209,16 +209,16 @@
</toolbarbutton> </toolbarbutton>
</toolbaritem> </toolbaritem>
<toolbarseparator class="sync-ui-item"/> <toolbarseparator class="sync-ui-item"/>
<toolbaritem id="appMenu-tp-container" hidden="true" closemenu="none"> <toolbaritem closemenu="none">
<toolbarbutton id="appMenu-tp-label" <toolbarbutton id="appMenu-tp-label"
tooltiptext="&trackingProtection.tooltip;" tooltiptext="&trackingProtection.tooltip;"
class="subviewbutton subviewbutton-iconic" class="subviewbutton subviewbutton-iconic"
oncommand="TrackingProtection.openPreferences('appMenu-trackingprotection'); PanelUI.hide();" oncommand="ContentBlocking.openPreferences('appMenu-trackingprotection'); PanelUI.hide();"
label="&trackingProtection.title;"/> label="&trackingProtection.title;"/>
<toolbarseparator orient="vertical"/> <toolbarseparator orient="vertical"/>
<toolbarbutton id="appMenu-tp-toggle" <toolbarbutton id="appMenu-tp-toggle"
enabled="false" enabled="false"
oncommand="TrackingProtection.onGlobalToggleCommand();" /> oncommand="ContentBlocking.onGlobalToggleCommand();" />
</toolbaritem> </toolbaritem>
<toolbarseparator id="appMenu-tp-separator" hidden="true" /> <toolbarseparator id="appMenu-tp-separator" hidden="true" />
<toolbarbutton id="appMenu-new-window-button" <toolbarbutton id="appMenu-new-window-button"

View file

@ -534,11 +534,7 @@ var Policies = {
setAndLockPref("pref.browser.homepage.disable_button.bookmark_page", true); setAndLockPref("pref.browser.homepage.disable_button.bookmark_page", true);
setAndLockPref("pref.browser.homepage.disable_button.restore_default", true); setAndLockPref("pref.browser.homepage.disable_button.restore_default", true);
} else { } else {
// The default pref for homepage is actually a complex pref. We need to setDefaultPref("browser.startup.homepage", homepages);
// set it in a special way such that it works properly
let homepagePrefVal = "data:text/plain,browser.startup.homepage=" +
homepages;
setDefaultPref("browser.startup.homepage", homepagePrefVal);
setDefaultPref("browser.startup.page", 1); setDefaultPref("browser.startup.page", 1);
runOncePerModification("setHomepage", homepages, () => { runOncePerModification("setHomepage", homepages, () => {
Services.prefs.clearUserPref("browser.startup.homepage"); Services.prefs.clearUserPref("browser.startup.homepage");

View file

@ -154,3 +154,14 @@ add_task(async function homepage_test_locked() {
await check_homepage({expectedURL: "http://example4.com/|http://example5.com/|http://example6.com/", await check_homepage({expectedURL: "http://example4.com/|http://example5.com/|http://example6.com/",
locked: true}); locked: true});
}); });
add_task(async function homepage_test_anchor_link() {
await setupPolicyEngineWithJson({
"policies": {
"Homepage": {
"URL": "http://example1.com/#test"
}
}
});
await check_homepage({expectedURL: "http://example1.com/#test"});
});

View file

@ -134,16 +134,18 @@ button.browser-style.default.focused {
border-color: #fff; border-color: #fff;
} }
/* Radio Buttons */ .browser-style > label {
.browser-style > input[type="radio"] {
display: none;
}
.browser-style > input[type="radio"] + label {
-moz-user-select: none; -moz-user-select: none;
} }
.browser-style > input[type="radio"] + label::before { .browser-style.disabled > label {
color: #999;
opacity: .5;
}
/* Radio Buttons */
.browser-style > input[type="radio"] {
-moz-appearance: none;
background-color: #fff; background-color: #fff;
background-position: center; background-position: center;
border: 1px solid #b1b1b1; border: 1px solid #b1b1b1;
@ -156,62 +158,48 @@ button.browser-style.default.focused {
width: 16px; width: 16px;
} }
.browser-style > input[type="radio"]:hover + label::before, .browser-style > input[type="radio"]:hover,
.browser-style.hover > input[type="radio"]:not(active) + label::before { .browser-style.hover > input[type="radio"]:not(:active) {
background-color: #fbfbfb; background-color: #fbfbfb;
border-color: #b1b1b1; border-color: #b1b1b1;
} }
.browser-style > input[type="radio"]:hover:active + label::before, .browser-style > input[type="radio"]:hover:active,
.browser-style.pressed > input[type="radio"]:not(active) + label::before { .browser-style.pressed > input[type="radio"]:not(:active) {
background-color: #ebebeb; background-color: #ebebeb;
border-color: #858585; border-color: #858585;
} }
.browser-style > input[type="radio"]:checked + label::before { .browser-style > input[type="radio"]:checked {
background-color: #0996f8; background-color: #0996f8;
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8Y2lyY2xlIGN4PSI4IiBjeT0iOCIgcj0iNCIgZmlsbD0iI2ZmZiIgLz4KPC9zdmc+Cg==); background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8Y2lyY2xlIGN4PSI4IiBjeT0iOCIgcj0iNCIgZmlsbD0iI2ZmZiIgLz4KPC9zdmc+Cg==);
border-color: #0670cc; border-color: #0670cc;
} }
.browser-style > input[type="radio"]:checked:hover + label::before, .browser-style > input[type="radio"]:checked:hover,
.browser-style.hover > input[type="radio"]:checked:not(active) + label::before { .browser-style.hover > input[type="radio"]:checked:not(:active) {
background-color: #0670cc; background-color: #0670cc;
border-color: #005bab; border-color: #005bab;
} }
.browser-style > input[type="radio"]:checked:hover:active + label::before, .browser-style > input[type="radio"]:checked:hover:active,
.browser-style.pressed > input[type="radio"]:checked:not(active) + label::before { .browser-style.pressed > input[type="radio"]:checked:not(:active) {
background-color: #005bab; background-color: #005bab;
border-color: #004480; border-color: #004480;
} }
.browser-style.disabled > input[type="radio"] + label, .browser-style.focused > input[type="radio"] {
.browser-style.disabled > input[type="radio"]:hover + label,
.browser-style.disabled > input[type="radio"]:hover:active + label {
color: #999;
opacity: .5;
}
.browser-style.focused > input[type="radio"] + label::before {
border-color: #0996f8; border-color: #0996f8;
box-shadow: 0 0 0 2px rgba(97, 181, 255, 0.75); box-shadow: 0 0 0 2px rgba(97, 181, 255, 0.75);
} }
.browser-style.focused > input[type="radio"]:checked + label::before { .browser-style.focused > input[type="radio"]:checked {
border-color: #fff; border-color: #fff;
} }
/* Checkboxes */ /* Checkboxes */
.browser-style > input[type="checkbox"] { .browser-style > input[type="checkbox"] {
display: none; -moz-appearance: none;
}
.browser-style > input[type="checkbox"] + label {
-moz-user-select: none;
}
.browser-style > input[type="checkbox"] + label::before {
background-color: #fff; background-color: #fff;
background-position: center; background-position: center;
border: 1px solid #b1b1b1; border: 1px solid #b1b1b1;
@ -223,49 +211,42 @@ button.browser-style.default.focused {
width: 16px; width: 16px;
} }
.browser-style > input[type="checkbox"]:hover + label::before, .browser-style > input[type="checkbox"]:hover,
.browser-style.hover > input[type="checkbox"]:not(active) + label::before { .browser-style.hover > input[type="checkbox"]:not(:active) {
background-color: #fbfbfb; background-color: #fbfbfb;
border-color: #b1b1b1; border-color: #b1b1b1;
} }
.browser-style > input[type="checkbox"]:hover:active + label::before, .browser-style > input[type="checkbox"]:hover:active,
.browser-style.pressed > input[type="checkbox"]:not(active) + label::before { .browser-style.pressed > input[type="checkbox"]:not(:active) {
background-color: #ebebeb; background-color: #ebebeb;
border-color: #858585; border-color: #858585;
} }
.browser-style > input[type="checkbox"]:checked + label::before { .browser-style > input[type="checkbox"]:checked {
background-color: #0996f8; background-color: #0996f8;
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBkPSJNNy43LDEyLjkgQzcuNCwxMy4zIDYuOCwxMy40IDYuNCwxMyBMMy4yLDkuOCBDMi44LDkuNCAyLjgsOC42IDMuMiw4LjIgQzMuNiw3LjggNC40LDcuOCA0LjgsOC4yIEw2LjksMTAuMyBMMTEuMSw0LjQgQzExLjUsMy45IDEyLjIsMy44IDEyLjcsNC4xIEMxMy4yLDQuNSAxMy4zLDUuMiAxMyw1LjcgTDcuNywxMi45IEw3LjcsMTIuOSBaIiBmaWxsPSIjZmZmIiAvPgo8L3N2Zz4K); background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBkPSJNNy43LDEyLjkgQzcuNCwxMy4zIDYuOCwxMy40IDYuNCwxMyBMMy4yLDkuOCBDMi44LDkuNCAyLjgsOC42IDMuMiw4LjIgQzMuNiw3LjggNC40LDcuOCA0LjgsOC4yIEw2LjksMTAuMyBMMTEuMSw0LjQgQzExLjUsMy45IDEyLjIsMy44IDEyLjcsNC4xIEMxMy4yLDQuNSAxMy4zLDUuMiAxMyw1LjcgTDcuNywxMi45IEw3LjcsMTIuOSBaIiBmaWxsPSIjZmZmIiAvPgo8L3N2Zz4K);
border-color: #0670cc; border-color: #0670cc;
} }
.browser-style > input[type="checkbox"]:checked:hover + label::before, .browser-style > input[type="checkbox"]:checked:hover,
.browser-style.hover > input[type="checkbox"]:checked:not(active) + label::before { .browser-style.hover > input[type="checkbox"]:checked:not(:active) {
background-color: #0670cc; background-color: #0670cc;
border-color: #005bab; border-color: #005bab;
} }
.browser-style > input[type="checkbox"]:checked:hover:active + label::before, .browser-style > input[type="checkbox"]:checked:hover:active,
.browser-style.pressed > input[type="checkbox"]:checked:not(active) + label::before { .browser-style.pressed > input[type="checkbox"]:checked:not(:active) {
background-color: #005bab; background-color: #005bab;
border-color: #004480; border-color: #004480;
} }
.browser-style.disabled > input[type="checkbox"] + label, .browser-style.focused > input[type="checkbox"] {
.browser-style.disabled > input[type="checkbox"]:hover + label,
.browser-style.disabled > input[type="checkbox"]:hover:active + label {
color: #999;
opacity: .5;
}
.browser-style.focused > input[type="checkbox"] + label::before {
border-color: #0996f8; border-color: #0996f8;
box-shadow: 0 0 0 2px rgba(97, 181, 255, 0.75); box-shadow: 0 0 0 2px rgba(97, 181, 255, 0.75);
} }
.browser-style.focused > input[type="checkbox"]:checked + label::before { .browser-style.focused > input[type="checkbox"]:checked {
border-color: #fff; border-color: #fff;
} }
@ -545,12 +526,12 @@ textarea.browser-style:focus:hover {
background-color: rgba(0, 0, 0, 0.1); background-color: rgba(0, 0, 0, 0.1);
} }
.panel-section-tabs-button.select.browser-styleed { .panel-section-tabs-button.selected {
box-shadow: 0 -1px 0 #0670cc inset, 0 -4px 0 #0996f8 inset; box-shadow: 0 -1px 0 #0670cc inset, 0 -4px 0 #0996f8 inset;
color: #0996f8; color: #0996f8;
} }
.panel-section-tabs-button.select.browser-styleed:hover { .panel-section-tabs-button.selected:hover {
color: #0670cc; color: #0670cc;
} }

View file

@ -23,12 +23,13 @@ async function testOptionsBrowserStyle(optionsUI, assertMessage) {
} }
} }
function verifyCheckboxOrRadio(type, element, expected) { function verifyCheckboxOrRadio(element, expected) {
let style = window.getComputedStyle(element); let style = window.getComputedStyle(element);
let styledBackground = element.checked ? "rgb(9, 150, 248)" : "rgb(255, 255, 255)";
if (browserStyle && expected.hasBrowserStyleClass) { if (browserStyle && expected.hasBrowserStyleClass) {
browser.test.assertEq("none", style.display, `Expected ${type} item to be hidden`); browser.test.assertEq(styledBackground, style.backgroundColor, assertMessage);
} else { } else {
browser.test.assertTrue(style.display != "none", `Expected ${type} item to be visible`); browser.test.assertTrue(style.backgroundColor != styledBackground, assertMessage);
} }
} }
@ -40,16 +41,16 @@ async function testOptionsBrowserStyle(optionsUI, assertMessage) {
let normalCheckbox1 = document.getElementById("normalCheckbox1"); let normalCheckbox1 = document.getElementById("normalCheckbox1");
let normalCheckbox2 = document.getElementById("normalCheckbox2"); let normalCheckbox2 = document.getElementById("normalCheckbox2");
let browserStyleCheckbox = document.getElementById("browserStyleCheckbox"); let browserStyleCheckbox = document.getElementById("browserStyleCheckbox");
verifyCheckboxOrRadio("checkbox", normalCheckbox1, {hasBrowserStyleClass: false}); verifyCheckboxOrRadio(normalCheckbox1, {hasBrowserStyleClass: false});
verifyCheckboxOrRadio("checkbox", normalCheckbox2, {hasBrowserStyleClass: false}); verifyCheckboxOrRadio(normalCheckbox2, {hasBrowserStyleClass: false});
verifyCheckboxOrRadio("checkbox", browserStyleCheckbox, {hasBrowserStyleClass: true}); verifyCheckboxOrRadio(browserStyleCheckbox, {hasBrowserStyleClass: true});
let normalRadio1 = document.getElementById("normalRadio1"); let normalRadio1 = document.getElementById("normalRadio1");
let normalRadio2 = document.getElementById("normalRadio2"); let normalRadio2 = document.getElementById("normalRadio2");
let browserStyleRadio = document.getElementById("browserStyleRadio"); let browserStyleRadio = document.getElementById("browserStyleRadio");
verifyCheckboxOrRadio("radio", normalRadio1, {hasBrowserStyleClass: false}); verifyCheckboxOrRadio(normalRadio1, {hasBrowserStyleClass: false});
verifyCheckboxOrRadio("radio", normalRadio2, {hasBrowserStyleClass: false}); verifyCheckboxOrRadio(normalRadio2, {hasBrowserStyleClass: false});
verifyCheckboxOrRadio("radio", browserStyleRadio, {hasBrowserStyleClass: true}); verifyCheckboxOrRadio(browserStyleRadio, {hasBrowserStyleClass: true});
browser.test.notifyPass("options-ui-browser_style"); browser.test.notifyPass("options-ui-browser_style");
}); });

View file

@ -18,8 +18,8 @@ skip-if = true # Bug 1113038 - Intermittent "Popup was opened"
skip-if = os == "linux" # Intermittent NS_ERROR_NOT_AVAILABLE [nsIUrlClassifierDBService.beginUpdate] skip-if = os == "linux" # Intermittent NS_ERROR_NOT_AVAILABLE [nsIUrlClassifierDBService.beginUpdate]
tag = trackingprotection tag = trackingprotection
support-files = support-files =
!/browser/base/content/test/general/benignPage.html !/browser/base/content/test/trackingUI/benignPage.html
!/browser/base/content/test/general/trackingPage.html !/browser/base/content/test/trackingUI/trackingPage.html
[browser_trackingProtection_tour.js] [browser_trackingProtection_tour.js]
tag = trackingprotection tag = trackingprotection
[browser_showMenu.js] [browser_showMenu.js]

View file

@ -1,9 +1,10 @@
"use strict"; "use strict";
const PREF_INTRO_COUNT = "privacy.trackingprotection.introCount"; const PREF_INTRO_COUNT = "privacy.trackingprotection.introCount";
const PREF_CB_ENABLED = "browser.contentblocking.enabled";
const PREF_TP_ENABLED = "privacy.trackingprotection.enabled"; const PREF_TP_ENABLED = "privacy.trackingprotection.enabled";
const BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/benignPage.html"; const BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/benignPage.html";
const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/trackingPage.html"; const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html";
const TOOLTIP_PANEL = document.getElementById("UITourTooltip"); const TOOLTIP_PANEL = document.getElementById("UITourTooltip");
const TOOLTIP_ANCHOR = document.getElementById("tracking-protection-icon-animatable-box"); const TOOLTIP_ANCHOR = document.getElementById("tracking-protection-icon-animatable-box");
@ -11,15 +12,17 @@ var {UrlClassifierTestUtils} = ChromeUtils.import("resource://testing-common/Url
registerCleanupFunction(function() { registerCleanupFunction(function() {
UrlClassifierTestUtils.cleanupTestTrackers(); UrlClassifierTestUtils.cleanupTestTrackers();
Services.prefs.clearUserPref(PREF_CB_ENABLED);
Services.prefs.clearUserPref(PREF_TP_ENABLED); Services.prefs.clearUserPref(PREF_TP_ENABLED);
Services.prefs.clearUserPref(PREF_INTRO_COUNT); Services.prefs.clearUserPref(PREF_INTRO_COUNT);
}); });
function allowOneIntro() { function allowOneIntro() {
Services.prefs.setIntPref(PREF_INTRO_COUNT, TrackingProtection.MAX_INTROS - 1); Services.prefs.setIntPref(PREF_INTRO_COUNT, window.ContentBlocking.MAX_INTROS - 1);
} }
add_task(async function setup_test() { add_task(async function setup_test() {
Services.prefs.setBoolPref(PREF_CB_ENABLED, true);
Services.prefs.setBoolPref(PREF_TP_ENABLED, true); Services.prefs.setBoolPref(PREF_TP_ENABLED, true);
await UrlClassifierTestUtils.addTestTrackers(); await UrlClassifierTestUtils.addTestTrackers();
}); });
@ -48,7 +51,7 @@ add_task(async function test_trackingPages() {
"Intro panel should appear"); "Intro panel should appear");
}); });
is(Services.prefs.getIntPref(PREF_INTRO_COUNT), TrackingProtection.MAX_INTROS, "Check intro count increased"); is(Services.prefs.getIntPref(PREF_INTRO_COUNT), window.ContentBlocking.MAX_INTROS, "Check intro count increased");
let step2URL = Services.urlFormatter.formatURLPref("privacy.trackingprotection.introURL") + let step2URL = Services.urlFormatter.formatURLPref("privacy.trackingprotection.introURL") +
"?step=2&newtab=true"; "?step=2&newtab=true";
@ -67,7 +70,7 @@ add_task(async function test_trackingPages() {
info("Clicking the main button"); info("Clicking the main button");
EventUtils.synthesizeMouseAtCenter(buttons.children[1], {}); EventUtils.synthesizeMouseAtCenter(buttons.children[1], {});
let tab = await tabPromise; let tab = await tabPromise;
is(Services.prefs.getIntPref(PREF_INTRO_COUNT), TrackingProtection.MAX_INTROS, is(Services.prefs.getIntPref(PREF_INTRO_COUNT), window.ContentBlocking.MAX_INTROS,
"Check intro count is at the max after opening step 2"); "Check intro count is at the max after opening step 2");
is(gBrowser.tabs.length, tabCount + 1, "Tour step 2 tab opened"); is(gBrowser.tabs.length, tabCount + 1, "Tour step 2 tab opened");
await panelHiddenPromise; await panelHiddenPromise;

View file

@ -29,12 +29,12 @@ add_UITour_task(function setup_block_target() {
// interferes with UITour as it does a teardown. All we really care about // interferes with UITour as it does a teardown. All we really care about
// is the permission manager entry but UITour tests shouldn't rely on that // is the permission manager entry but UITour tests shouldn't rely on that
// implementation detail. // implementation detail.
TrackingProtection.disableForCurrentPage(); window.ContentBlocking.disableForCurrentPage();
}); });
add_UITour_task(async function test_block_target() { add_UITour_task(async function test_block_target() {
await checkToggleTarget("controlCenter-trackingBlock"); await checkToggleTarget("controlCenter-trackingBlock");
TrackingProtection.enableForCurrentPage(); window.ContentBlocking.enableForCurrentPage();
}); });

View file

@ -918,29 +918,54 @@ you can use these alternative items. Otherwise, their values should be empty. -
<!ENTITY getUserMedia.audioCapture.label "Audio from the tab will be shared."> <!ENTITY getUserMedia.audioCapture.label "Audio from the tab will be shared.">
<!ENTITY getUserMedia.allWindowsShared.message "All visible windows on your screen will be shared."> <!ENTITY getUserMedia.allWindowsShared.message "All visible windows on your screen will be shared.">
<!ENTITY trackingProtection.on "Tracking Protection: ON"> <!ENTITY contentBlocking.title "Content Blocking">
<!ENTITY trackingProtection.off "Tracking Protection: OFF"> <!ENTITY contentBlocking.detected "Blockable content detected on this site.">
<!ENTITY contentBlocking.notDetected "No blockable content detected on this page">
<!ENTITY contentBlocking.disabled.label "Disabled">
<!ENTITY contentBlocking.disabled.tooltip "You have disabled Content Blocking.">
<!ENTITY contentBlocking.exception.tooltip "You have disabled Content Blocking for this site.">
<!ENTITY contentBlocking.fastBlock.label "Slow-Loading Trackers">
<!-- LOCALIZATION NOTE (contentBlocking.fastBlock.blocked.label):
This label signals that this type of content blocking is turned
ON and is successfully blocking malicious/slow content, so this is
a positive thing. It forms the end of the (imaginary) sentence
"Slow-Loading Trackers [are] Blocked"-->
<!ENTITY contentBlocking.fastBlock.blocked.label "Blocked">
<!-- LOCALIZATION NOTE (contentBlocking.fastBlock.add.label):
This is displayed as a link to preferences, where the user can add
this specific type of content blocking. When this text is shown
the type of content blocking is currently not enabled. -->
<!ENTITY contentBlocking.fastBlock.add.label "Add Blocking…">
<!ENTITY contentBlocking.trackingProtection.label "Trackers">
<!-- LOCALIZATION NOTE (contentBlocking.trackingProtection.blocked.label):
This label signals that this type of content blocking is turned
ON and is successfully blocking malicious/slow content, so this is
a positive thing. It forms the end of the (imaginary) sentence
"Trackers [are] Blocked"-->
<!ENTITY contentBlocking.trackingProtection.blocked.label "Blocked">
<!-- LOCALIZATION NOTE (contentBlocking.trackingProtection.add.label):
This is displayed as a link to preferences, where the user can add
this specific type of content blocking. When this text is shown
the type of content blocking is currently not enabled. -->
<!ENTITY contentBlocking.trackingProtection.add.label "Add Blocking…">
<!ENTITY trackingProtection.title "Tracking Protection"> <!ENTITY trackingProtection.title "Tracking Protection">
<!ENTITY trackingProtection.tooltip "Open Tracking Protection Preferences"> <!ENTITY trackingProtection.tooltip "Open Tracking Protection Preferences">
<!ENTITY trackingProtection.detectedBlocked4 "&brandShortName; is blocking parts of this page that may track your browsing.">
<!ENTITY trackingProtection.detectedNotBlocked5 "&brandShortName; has detected elements that may track your browsing.">
<!ENTITY trackingProtection.detectedException "&brandShortName; has detected elements that may track your browsing. You have disabled protection for this site.">
<!ENTITY trackingProtection.notDetected5 "No tracking elements detected on this page.">
<!ENTITY trackingProtection.notDetectedException "No tracking elements detected on this page. You have disabled protection for this site.">
<!ENTITY trackingProtection.reloadRequired2 "You have enabled Tracking Protection. Reload this page to block all trackers.">
<!-- LOCALIZATION NOTE (trackingProtection.unblock3.label, trackingProtection.unblock3.accesskey): <!-- LOCALIZATION NOTE (trackingProtection.unblock3.label, trackingProtection.unblock3.accesskey):
The associated button with this label and accesskey is only shown when opening the control The associated button with this label and accesskey is only shown when opening the control
center while looking at a site with trackers in NON-private browsing mode. --> center while looking at a site with trackers in NON-private browsing mode. -->
<!ENTITY trackingProtection.unblock3.label "Disable For This Site"> <!ENTITY trackingProtection.unblock4.label "Disable Blocking For This Site">
<!ENTITY trackingProtection.unblock3.accesskey "D"> <!ENTITY trackingProtection.unblock4.accesskey "D">
<!-- LOCALIZATION NOTE (trackingProtection.unblockPrivate3.label, trackingProtection.unblockPrivate3.accesskey): <!-- LOCALIZATION NOTE (trackingProtection.unblockPrivate3.label, trackingProtection.unblockPrivate3.accesskey):
The associated button with this label and accesskey is only shown when opening the control The associated button with this label and accesskey is only shown when opening the control
center while looking at a site with trackers in PRIVATE browsing mode. --> center while looking at a site with trackers in PRIVATE browsing mode. -->
<!ENTITY trackingProtection.unblockPrivate3.label "Disable For This Session"> <!ENTITY trackingProtection.unblockPrivate4.label "Disable Blocking Temporarily">
<!ENTITY trackingProtection.unblockPrivate3.accesskey "D"> <!ENTITY trackingProtection.unblockPrivate4.accesskey "D">
<!ENTITY trackingProtection.block4.label "Enable For This Site"> <!ENTITY trackingProtection.block5.label "Enable Blocking For This Site">
<!ENTITY trackingProtection.block4.accesskey "E"> <!ENTITY trackingProtection.block5.accesskey "E">
<!ENTITY trackingProtection.reload2.label "Reload Page"> <!ENTITY trackingProtection.reload2.label "Reload Page">
<!ENTITY trackingProtection.reload2.accesskey "R"> <!ENTITY trackingProtection.reload2.accesskey "R">

View file

@ -525,6 +525,11 @@ identity.extension.label=Extension (%S)
identity.extension.tooltip=Loaded by extension: %S identity.extension.tooltip=Loaded by extension: %S
identity.showDetails.tooltip=Show connection details identity.showDetails.tooltip=Show connection details
contentBlocking.title=Content Blocking
contentBlocking.tooltip=Open Content Blocking Preferences
contentBlocking.toggle.enable.tooltip=Enable Content Blocking
contentBlocking.toggle.disable.tooltip=Disable Content Blocking
trackingProtection.intro.title=How Tracking Protection works trackingProtection.intro.title=How Tracking Protection works
# LOCALIZATION NOTE (trackingProtection.intro.description2): # LOCALIZATION NOTE (trackingProtection.intro.description2):
# %S is brandShortName. This string should match the one from Step 1 of the tour # %S is brandShortName. This string should match the one from Step 1 of the tour

View file

@ -70,8 +70,8 @@
} }
#identity-popup-mainView { #identity-popup-mainView {
min-width: 30em; min-width: 33em;
max-width: 30em; max-width: 33em;
} }
.identity-popup-section:not(:first-child) { .identity-popup-section:not(:first-child) {
@ -80,7 +80,7 @@
.identity-popup-security-content, .identity-popup-security-content,
#identity-popup-permissions-content, #identity-popup-permissions-content,
#tracking-protection-content { #identity-popup-content-blocking-content {
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 1em 1em; background-position: 1em 1em;
background-size: 24px auto; background-size: 24px auto;
@ -95,7 +95,7 @@
.identity-popup-security-content:-moz-locale-dir(rtl), .identity-popup-security-content:-moz-locale-dir(rtl),
#identity-popup-permissions-content:-moz-locale-dir(rtl), #identity-popup-permissions-content:-moz-locale-dir(rtl),
#tracking-protection-content:-moz-locale-dir(rtl) { #identity-popup-content-blocking-content:-moz-locale-dir(rtl) {
background-position: calc(100% - 1em) 1em; background-position: calc(100% - 1em) 1em;
} }
@ -147,19 +147,23 @@
/* CONTENT */ /* CONTENT */
#identity-popup-content-blocking-disabled-label,
.identity-popup-content-blocking-category-label,
.identity-popup-content-blocking-category-state-label,
.identity-popup-content-blocking-category-add-blocking,
.identity-popup-permission-label, .identity-popup-permission-label,
.identity-popup-permission-state-label, .identity-popup-permission-state-label,
.identity-popup-security-content > description, .identity-popup-security-content > description,
#identity-popup-security-descriptions > description, #identity-popup-security-descriptions > description,
#identity-popup-securityView-body > description, #identity-popup-securityView-body > description,
#identity-popup-permissions-content > description, #identity-popup-permissions-content > description,
#tracking-protection-content > description { #identity-popup-content-blocking-content > description {
font-size: 110%; font-size: 110%;
margin: 0; margin: 0;
} }
#identity-popup-permissions-content > description, #identity-popup-permissions-content > description,
#tracking-protection-content > description { #identity-popup-content-blocking-content > description {
color: var(--panel-disabled-color); color: var(--panel-disabled-color);
} }
@ -182,12 +186,18 @@
.identity-popup-warning-gray { .identity-popup-warning-gray {
padding-inline-start: 24px; padding-inline-start: 24px;
background: url(chrome://browser/skin/controlcenter/warning-gray.svg) no-repeat 0 50%; background: url(chrome://browser/skin/controlcenter/warning.svg) no-repeat 0 50%;
fill: #808080;
stroke: #fff;
-moz-context-properties: fill, stroke;
} }
.identity-popup-warning-yellow { .identity-popup-warning-yellow {
padding-inline-start: 24px; padding-inline-start: 24px;
background: url(chrome://browser/skin/controlcenter/warning-yellow.svg) no-repeat 0 50%; background: url(chrome://browser/skin/controlcenter/warning.svg) no-repeat 0 50%;
fill: #ffbf00;
stroke: #fff;
-moz-context-properties: fill, stroke;
} }
.identity-popup-warning-gray:-moz-locale-dir(rtl), .identity-popup-warning-gray:-moz-locale-dir(rtl),
@ -300,59 +310,121 @@ description#identity-popup-content-verifier,
margin-inline-end: 0; margin-inline-end: 0;
} }
/* TRACKING PROTECTION */ /* CONTENT BLOCKING / TRACKING PROTECTION */
#tracking-protection-content { #identity-popup-content-blocking-content {
background-image: url("chrome://browser/skin/controlcenter/tracking-protection.svg"); background-image: url("chrome://browser/skin/controlcenter/tracking-protection.svg");
} }
#tracking-protection-content[enabled="false"], /* We can currently show either the old tracking protection-only UI, which has "Tracking Protection"
#tracking-protection-content[hasException], * as a label, or the new content blocking UI which has a different label and also a list of
#tracking-protection-content[state="loaded-tracking-content"] { * categories of blockers. This rule hides elements depending on which UI we want to show */
background-image: url("chrome://browser/skin/controlcenter/tracking-protection-disabled.svg"); #identity-popup-content-blocking-content[contentBlockingUI] #tracking-protection-label,
} #identity-popup-content-blocking-content:not([contentBlockingUI]) #content-blocking-label,
#identity-popup-content-blocking-content:not([contentBlockingUI]) > #identity-popup-content-blocking-category-list {
/* Show the "on" label by default, except when TP is disabled or there's a local exception. */
#tracking-protection-label-off,
#tracking-protection-content[enabled="false"] #tracking-protection-label-on,
#tracking-protection-content[hasException] #tracking-protection-label-on,
#tracking-protection-content[state="loaded-tracking-content"] #tracking-protection-label-on {
display: none; display: none;
} }
#tracking-protection-label-on, /* Disabled label */
#tracking-protection-content[enabled="false"] #tracking-protection-label-off,
#tracking-protection-content[hasException] #tracking-protection-label-off, #identity-popup-content-blocking-disabled-label {
#tracking-protection-content[state="loaded-tracking-content"] #tracking-protection-label-off { padding: 0px 5px;
border-radius: 3px;
margin: 5px;
display: none;
color: #fff;
}
#identity-popup-content-blocking-content[hasException] #identity-popup-content-blocking-disabled-label {
display: -moz-box; display: -moz-box;
background-color: #d7b600;
stroke: #d7b600;
} }
#tracking-protection-content > description { #identity-popup-content-blocking-content[enabled][hasException] #identity-popup-content-blocking-disabled-label-global {
display: none; display: none;
} }
#identity-popup-content-blocking-content:not([enabled]) #identity-popup-content-blocking-disabled-label {
display: -moz-box;
background-color: #d70022;
stroke: #d70022;
}
#identity-popup-content-blocking-content:not([enabled]) #identity-popup-content-blocking-disabled-label-exception {
display: none;
}
#identity-popup-content-blocking-disabled-label > label {
margin: 0;
line-height: 18px;
}
#identity-popup-content-blocking-disabled-label > image {
list-style-image: url(chrome://browser/skin/controlcenter/warning.svg);
fill: currentColor;
-moz-context-properties: fill, stroke;
margin-inline-end: 4px;
height: 13px;
width: 13px;
}
/* Content Blocking categories */
#identity-popup-content-blocking-category-list {
margin-top: 10px;
}
/* Don't show the categories when no trackers were detected. */
#identity-popup-content-blocking-content:not([detected]) > #identity-popup-content-blocking-category-list {
display: none;
}
/* Show the "detected"/"not detected" message depending on the content state. */
#identity-popup-content-blocking-content:not([detected]) > #identity-popup-content-blocking-detected,
#identity-popup-content-blocking-content[detected] > #identity-popup-content-blocking-not-detected {
display: none;
}
#identity-popup-content-blocking-content[enabled][hasException] .identity-popup-content-blocking-category-state-label,
.identity-popup-content-blocking-category:not(.blocked) .identity-popup-content-blocking-category-state-label {
display: none;
}
.identity-popup-content-blocking-category.blocked .identity-popup-content-blocking-category-add-blocking {
display: none;
}
.fastblock-icon {
list-style-image: url(chrome://browser/skin/controlcenter/slowtrackers.svg);
}
#identity-popup-content-blocking-category-fastblock.blocked > .fastblock-icon {
list-style-image: url(chrome://browser/skin/controlcenter/slowtrackers-disabled.svg);
}
.tracking-protection-icon {
list-style-image: url(chrome://browser/skin/controlcenter/trackers.svg);
}
#identity-popup-content-blocking-category-tracking-protection.blocked > .tracking-protection-icon {
list-style-image: url(chrome://browser/skin/controlcenter/trackers-disabled.svg);
}
/* Content Blocking action button */
.tracking-protection-button { .tracking-protection-button {
margin: 1em 0 0; margin: 1em 0 0;
display: none; display: none;
} }
/* Show the right tracking descriptions and buttons for the corresponding state. */ /* Show the right action buttons depending on content state */
/* Offer to temporarily add an exception in private mode. */
/* Default state / Tracking not detected */ #main-window:not([privatebrowsingmode]) #identity-popup-content-blocking-content[enabled][detected]:not([hasException]) > #tracking-action-unblock,
#tracking-protection-content:not([state]):-moz-any([enabled="false"], :not([hasException])) > #tracking-not-detected, /* Offer to permanently add an exception in normal mode. */
#tracking-protection-content:not([state])[enabled="true"][hasException] > #tracking-not-detected-exception, #main-window[privatebrowsingmode] #identity-popup-content-blocking-content[enabled][detected]:not([hasException]) > #tracking-action-unblock-private,
/* Blocking tracking, offer buttons to unblock (depending on PBM). */ /* If there's an exception just offer to remove the exception again. */
#tracking-protection-content:not([hasException])[state="blocked-tracking-content"] > #tracking-blocked, #identity-popup-content-blocking-content[enabled][hasException] > #tracking-action-block {
#main-window:not([privatebrowsingmode]) #tracking-protection-content:not([hasException])[state="blocked-tracking-content"] > #tracking-action-unblock,
#main-window[privatebrowsingmode] #tracking-protection-content[state="blocked-tracking-content"] > #tracking-action-unblock-private,
/* Enabled and no exception but trackers loaded, probably needs a reload */
#tracking-protection-content[enabled="true"]:not([hasException])[state="loaded-tracking-content"] > #tracking-reload-required,
#tracking-protection-content[enabled="true"]:not([hasException])[state="loaded-tracking-content"] > #tracking-action-reload,
/* Tracking Loaded */
#tracking-protection-content[state="loaded-tracking-content"][enabled="false"] > #tracking-loaded,
#tracking-protection-content[enabled="true"][hasException] > #tracking-loaded-exception,
/* Has an exception, offer to block the site again. */
#tracking-protection-content[enabled="true"][hasException] > #tracking-action-block {
display: -moz-box; display: -moz-box;
} }
@ -377,6 +449,7 @@ description#identity-popup-content-verifier,
min-height: 24px; min-height: 24px;
} }
#identity-popup-content-blocking-category-list,
#identity-popup-permission-list { #identity-popup-permission-list {
/* Offset the padding set on #identity-popup-permissions-content so that it /* Offset the padding set on #identity-popup-permissions-content so that it
shows up just below the section. The permission icons are 16px wide and shows up just below the section. The permission icons are 16px wide and
@ -384,6 +457,7 @@ description#identity-popup-content-verifier,
margin-inline-start: calc(-1em - 16px); margin-inline-start: calc(-1em - 16px);
} }
.identity-popup-content-blocking-category,
.identity-popup-permission-item { .identity-popup-permission-item {
min-height: 24px; min-height: 24px;
} }
@ -392,6 +466,7 @@ description#identity-popup-content-verifier,
margin-top: 5px; margin-top: 5px;
} }
.identity-popup-content-blocking-category-icon,
.identity-popup-permission-icon { .identity-popup-permission-icon {
width: 16px; width: 16px;
height: 16px; height: 16px;
@ -407,6 +482,8 @@ description#identity-popup-content-verifier,
50% { opacity: 0; } 50% { opacity: 0; }
} }
.identity-popup-content-blocking-category-label,
.identity-popup-content-blocking-category-state-label,
.identity-popup-permission-label, .identity-popup-permission-label,
.identity-popup-permission-state-label { .identity-popup-permission-state-label {
/* We need to align the action buttons and permission icons with the text. /* We need to align the action buttons and permission icons with the text.
@ -417,13 +494,20 @@ description#identity-popup-content-verifier,
margin-top: -0.1em; margin-top: -0.1em;
} }
.identity-popup-content-blocking-category-label,
.identity-popup-permission-label { .identity-popup-permission-label {
margin-inline-start: 1em; margin-inline-start: 1em;
} }
.identity-popup-content-blocking-category-state-label,
.identity-popup-content-blocking-category-add-blocking,
.identity-popup-permission-state-label { .identity-popup-permission-state-label {
margin-inline-end: 5px; margin-inline-end: 5px;
text-align: end; text-align: end;
}
.identity-popup-content-blocking-category-state-label,
.identity-popup-permission-state-label {
color: var(--panel-disabled-color); color: var(--panel-disabled-color);
} }

View file

@ -0,0 +1,7 @@
<!-- 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" width="16" height="16" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity">
<path fill="context-fill" d="M14,6c-1,0-1.746,1-2.246,1.992-.047-.193-.115-.38-.176-.57L8,11H9v1.5a.5.5,0,0,0,.5.5h2a.5.5,0,0,0,.5-.5V10h2a2,2,0,0,0,0-4Z"/>
<path fill="context-fill" d="M14.707,1.293a1,1,0,0,0-1.414,0L9.944,4.641A5.359,5.359,0,0,0,6,3C2,3,0,6.686,0,10H1v2.5a.5.5,0,0,0,.5.5h.086l-.293.293a1,1,0,1,0,1.414,1.414l12-12A1,1,0,0,0,14.707,1.293Z"/>
</svg>

After

Width:  |  Height:  |  Size: 724 B

View file

@ -0,0 +1,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" width="16" height="16" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity">
<path fill="context-fill" d="M9.306,9.694c.071.416.132.8.15,1.1a4.938,4.938,0,0,1-.058,1,18.45,18.45,0,0,0,3.478.193c.016-.167.033-.343.052-.537.2-2.032.885-2.574,1.028-3.707a5.874,5.874,0,0,0-.223-2.475Z"/>
<path fill="context-fill" d="M9.236,12.767c-.069.365-.136.737-.177,1.13a1.675,1.675,0,0,0,1.579,2.079c1.235.16,1.779-.976,1.944-1.635a8.594,8.594,0,0,0,.2-1.35c-.2.005-.4.009-.606.009A18.258,18.258,0,0,1,9.236,12.767Z"/>
<path fill="context-fill" d="M14.707,1.293a1,1,0,0,0-1.414,0L6.547,8.039c0-.083-.008-.167,0-.249a25.267,25.267,0,0,0,.432-3.949C6.724,1.833,5.853-.177,4.414,0,2.8.2,1.766,2.521,2.045,4.742c.143,1.133.828,1.675,1.028,3.707.019.194.036.37.052.536A20.41,20.41,0,0,0,5.67,8.916L4.614,9.972c-.256.012-.514.028-.76.028-.221,0-.432,0-.636-.01A9.6,9.6,0,0,0,3.387,11.2L1.293,13.293a1,1,0,1,0,1.414,1.414l12-12A1,1,0,0,0,14.707,1.293Z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -1,8 +0,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/. -->
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="context-fill" fill-opacity="context-fill-opacity">
<path d="M24.852 14.291c-.391 4.287-1.125 6.49-3.021 9.065A9.562 9.562 0 0 1 16 26.989a9.679 9.679 0 0 1-4.958-2.617l-1.415 1.415a11.419 11.419 0 0 0 6.261 3.207l.112.012.112-.012a11.4 11.4 0 0 0 7.33-4.452c2.12-2.879 2.977-5.42 3.4-10.07.121-1.339.151-4.013.155-6.057l-2.013 2.014c-.016 1.471-.053 2.996-.132 3.862z"/>
<path d="M16 24.336v-4.922l-2.921 2.921a6.513 6.513 0 0 0 2.919 2z"/>
<path d="M28.707 3.293a1 1 0 0 0-1.414 0l-1.576 1.576a2.59 2.59 0 0 0-.944-.377L16 2.985 7.227 4.491A2.69 2.69 0 0 0 5 7.153c-.006 2.031.007 5.681.155 7.319.349 3.823 1.007 6.221 2.4 8.554l-4.262 4.267a1 1 0 1 0 1.414 1.414l24-24a1 1 0 0 0 0-1.414zM10 8.78c.021 2.264.073 3.979.148 4.8a20.908 20.908 0 0 0 1.124 5.73l-2.244 2.248a17.451 17.451 0 0 1-1.88-7.267C7 12.676 7 8.765 7 7.159a.7.7 0 0 1 .563-.7L16 5.015l8.169 1.4L16 14.586V7.75z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -1,9 +0,0 @@
<?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="16" height="16" viewBox="0 0 16 16">
<path fill="#808080" d="M14.8,12.5L9.3,1.9C9,1.3,8.5,1,8,1C7.5,1,7,1.3,6.7,1.9L1.2,12.5c-0.3,0.6-0.3,1.2,0,1.7C1.5,14.7,2,15,2.6,15h10.8 c0.6,0,1.1-0.3,1.4-0.8C15.1,13.7,15.1,13.1,14.8,12.5z"/>
<path fill="#fff" d="M8,11c-0.8,0-1.5,0.7-1.5,1.5C6.5,13.3,7.2,14,8,14 c0.8,0,1.5-0.7,1.5-1.5C9.5,11.7,8.8,11,8,11z M8,10L8,10C8.6,10,9,9.6,9,9l0.2-4.2c0-0.7-0.5-1.2-1.2-1.2S6.8,4.1,6.8,4.8L7,9 C7,9.6,7.4,10,8,10z"/>
</svg>

Before

Width:  |  Height:  |  Size: 805 B

View file

@ -1,9 +0,0 @@
<?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="16" height="16" viewBox="0 0 16 16">
<path fill="#ffbf00" d="M14.8,12.5L9.3,1.9C9,1.3,8.5,1,8,1C7.5,1,7,1.3,6.7,1.9L1.2,12.5c-0.3,0.6-0.3,1.2,0,1.7C1.5,14.7,2,15,2.6,15h10.8 c0.6,0,1.1-0.3,1.4-0.8C15.1,13.7,15.1,13.1,14.8,12.5z"/>
<path fill="#fff" d="M8,11c-0.8,0-1.5,0.7-1.5,1.5C6.5,13.3,7.2,14,8,14 c0.8,0,1.5-0.7,1.5-1.5C9.5,11.7,8.8,11,8,11z M8,10L8,10C8.6,10,9,9.6,9,9l0.2-4.2c0-0.7-0.5-1.2-1.2-1.2S6.8,4.1,6.8,4.8L7,9 C7,9.6,7.4,10,8,10z"/>
</svg>

Before

Width:  |  Height:  |  Size: 805 B

View file

@ -0,0 +1,7 @@
<!-- 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" width="16" height="16" viewBox="0 0 16 16">
<path fill="context-fill" d="M14.8,12.5L9.3,1.9C9,1.3,8.5,1,8,1C7.5,1,7,1.3,6.7,1.9L1.2,12.5c-0.3,0.6-0.3,1.2,0,1.7C1.5,14.7,2,15,2.6,15h10.8 c0.6,0,1.1-0.3,1.4-0.8C15.1,13.7,15.1,13.1,14.8,12.5z"/>
<path fill="context-stroke" d="M8,11c-0.8,0-1.5,0.7-1.5,1.5C6.5,13.3,7.2,14,8,14 c0.8,0,1.5-0.7,1.5-1.5C9.5,11.7,8.8,11,8,11z M8,10L8,10C8.6,10,9,9.6,9,9l0.2-4.2c0-0.7-0.5-1.2-1.2-1.2S6.8,4.1,6.8,4.8L7,9 C7,9.6,7.4,10,8,10z"/>
</svg>

After

Width:  |  Height:  |  Size: 733 B

View file

@ -154,7 +154,8 @@
margin-inline-end: -20px; margin-inline-end: -20px;
} }
#tracking-protection-icon-box[state] { #tracking-protection-icon-box[active],
#tracking-protection-icon-box[hasException] {
margin-inline-end: 0px; margin-inline-end: 0px;
visibility: visible; visibility: visible;
} }
@ -163,7 +164,7 @@
transition: margin-left 200ms ease-out, margin-right 200ms ease-out; transition: margin-left 200ms ease-out, margin-right 200ms ease-out;
} }
#tracking-protection-icon-box:not([hasException])[state="blocked-tracking-content"][animationsenabled] > #tracking-protection-icon, #tracking-protection-icon-box:not([hasException])[active][animationsenabled] > #tracking-protection-icon,
#tracking-protection-icon-box:not([animationsenabled]) > #tracking-protection-icon-animatable-box { #tracking-protection-icon-box:not([animationsenabled]) > #tracking-protection-icon-animatable-box {
display: none; display: none;
} }
@ -177,7 +178,7 @@
height: 20px; height: 20px;
} }
#tracking-protection-icon-box:not([hasException])[state="blocked-tracking-content"] #tracking-protection-icon-animatable-image { #tracking-protection-icon-box:not([hasException])[active] #tracking-protection-icon-animatable-image {
background-image: url(chrome://browser/skin/tracking-protection-animation.svg); background-image: url(chrome://browser/skin/tracking-protection-animation.svg);
transform: translateX(-1232px); transform: translateX(-1232px);
width: 1248px; width: 1248px;
@ -187,29 +188,26 @@
-moz-context-properties: fill, fill-opacity; -moz-context-properties: fill, fill-opacity;
} }
#tracking-protection-icon-box[state="blocked-tracking-content"] #tracking-protection-icon-animatable-image:-moz-locale-dir(rtl) { #tracking-protection-icon-box[active] #tracking-protection-icon-animatable-image:-moz-locale-dir(rtl) {
transform: scaleX(-1) translateX(-1232px); transform: scaleX(-1) translateX(-1232px);
} }
#tracking-protection-icon-box[state="blocked-tracking-content"][animate] #tracking-protection-icon-animatable-image { #tracking-protection-icon-box[active][animate] #tracking-protection-icon-animatable-image {
animation-name: tp-icon-animation; animation-name: tp-icon-animation;
animation-timing-function: steps(77); animation-timing-function: steps(77);
animation-duration: 3s; animation-duration: 3s;
animation-fill-mode: forwards; animation-fill-mode: forwards;
} }
#tracking-protection-icon-box[state="blocked-tracking-content"][animate] #tracking-protection-icon-animatable-image:-moz-locale-dir(rtl) { #tracking-protection-icon-box[active][animate] #tracking-protection-icon-animatable-image:-moz-locale-dir(rtl) {
animation-name: tp-icon-animation-rtl; animation-name: tp-icon-animation-rtl;
} }
#tracking-protection-icon-box[state="blocked-tracking-content"] > #tracking-protection-icon { #tracking-protection-icon-box[active] > #tracking-protection-icon {
list-style-image: url(chrome://browser/skin/tracking-protection.svg); list-style-image: url(chrome://browser/skin/tracking-protection.svg);
} }
/* Override the blocked tracking content rule for cases when the user has added an exception #tracking-protection-icon-box[hasException] > #tracking-protection-icon {
* on a different tab to signify that protection is disabled now */
#tracking-protection-icon-box[hasException][state="blocked-tracking-content"] > #tracking-protection-icon,
#tracking-protection-icon-box[state="loaded-tracking-content"] > #tracking-protection-icon {
list-style-image: url(chrome://browser/skin/tracking-protection-disabled.svg); list-style-image: url(chrome://browser/skin/tracking-protection-disabled.svg);
} }

View file

@ -28,11 +28,11 @@
skin/classic/browser/controlcenter/extension.svg (../shared/controlcenter/extension.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/permissions.svg (../shared/controlcenter/permissions.svg)
skin/classic/browser/controlcenter/slowtrackers.svg (../shared/controlcenter/slowtrackers.svg) skin/classic/browser/controlcenter/slowtrackers.svg (../shared/controlcenter/slowtrackers.svg)
skin/classic/browser/controlcenter/slowtrackers-disabled.svg (../shared/controlcenter/slowtrackers-disabled.svg)
skin/classic/browser/controlcenter/trackers.svg (../shared/controlcenter/trackers.svg) skin/classic/browser/controlcenter/trackers.svg (../shared/controlcenter/trackers.svg)
skin/classic/browser/controlcenter/trackers-disabled.svg (../shared/controlcenter/trackers-disabled.svg)
skin/classic/browser/controlcenter/tracking-protection.svg (../shared/controlcenter/tracking-protection.svg) skin/classic/browser/controlcenter/tracking-protection.svg (../shared/controlcenter/tracking-protection.svg)
skin/classic/browser/controlcenter/tracking-protection-disabled.svg (../shared/controlcenter/tracking-protection-disabled.svg) skin/classic/browser/controlcenter/warning.svg (../shared/controlcenter/warning.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/empty-overflow-panel.png (../shared/customizableui/empty-overflow-panel.png) skin/classic/browser/customizableui/empty-overflow-panel.png (../shared/customizableui/empty-overflow-panel.png)
skin/classic/browser/customizableui/empty-overflow-panel@2x.png (../shared/customizableui/empty-overflow-panel@2x.png) skin/classic/browser/customizableui/empty-overflow-panel@2x.png (../shared/customizableui/empty-overflow-panel@2x.png)
skin/classic/browser/customizableui/density-compact.svg (../shared/customizableui/density-compact.svg) skin/classic/browser/customizableui/density-compact.svg (../shared/customizableui/density-compact.svg)

View file

@ -1,15 +1,15 @@
{ {
"llvm_revision": "336407", "llvm_revision": "338869",
"stages": "3", "stages": "3",
"build_libcxx": true, "build_libcxx": true,
"build_type": "Release", "build_type": "Release",
"assertions": false, "assertions": false,
"llvm_repo": "https://llvm.org/svn/llvm-project/llvm/trunk", "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_700/rc1",
"clang_repo": "https://llvm.org/svn/llvm-project/cfe/trunk", "clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_700/rc1",
"lld_repo": "https://llvm.org/svn/llvm-project/lld/trunk", "lld_repo": "https://llvm.org/svn/llvm-project/lld/tags/RELEASE_700/rc1",
"compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/trunk", "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_700/rc1",
"libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/trunk", "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_700/rc1",
"libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/trunk", "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/tags/RELEASE_700/rc1",
"python_path": "/usr/bin/python2.7", "python_path": "/usr/bin/python2.7",
"gcc_dir": "/builds/worker/workspace/build/src/gcc", "gcc_dir": "/builds/worker/workspace/build/src/gcc",
"cc": "/builds/worker/workspace/build/src/gcc/bin/gcc", "cc": "/builds/worker/workspace/build/src/gcc/bin/gcc",

View file

@ -1,15 +1,15 @@
{ {
"llvm_revision": "337146", "llvm_revision": "338869",
"stages": "3", "stages": "3",
"build_libcxx": true, "build_libcxx": true,
"build_type": "Release", "build_type": "Release",
"assertions": false, "assertions": false,
"llvm_repo": "https://llvm.org/svn/llvm-project/llvm/trunk", "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_700/rc1",
"clang_repo": "https://llvm.org/svn/llvm-project/cfe/trunk", "clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_700/rc1",
"lld_repo": "https://llvm.org/svn/llvm-project/lld/trunk", "lld_repo": "https://llvm.org/svn/llvm-project/lld/tags/RELEASE_700/rc1",
"compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/trunk", "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_700/rc1",
"libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/trunk", "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_700/rc1",
"libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/trunk", "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/tags/RELEASE_700/rc1",
"python_path": "/usr/bin/python2.7", "python_path": "/usr/bin/python2.7",
"gcc_dir": "/builds/worker/workspace/build/src/gcc", "gcc_dir": "/builds/worker/workspace/build/src/gcc",
"cc": "/builds/worker/workspace/build/src/gcc/bin/gcc", "cc": "/builds/worker/workspace/build/src/gcc/bin/gcc",

View file

@ -629,6 +629,7 @@ support-files =
examples/script-switching-01.js examples/script-switching-01.js
examples/times2.js examples/times2.js
examples/doc_rr_basic.html examples/doc_rr_basic.html
examples/doc_rr_continuous.html
[browser_dbg-asm.js] [browser_dbg-asm.js]
[browser_dbg-async-stepping.js] [browser_dbg-async-stepping.js]
@ -720,3 +721,21 @@ skip-if = debug || (verify && (os == 'win')) || (os == "win" && os_version == "6
skip-if = true skip-if = true
[browser_dbg_rr_breakpoints-01.js] [browser_dbg_rr_breakpoints-01.js]
skip-if = os != "mac" || debug || !nightly_build skip-if = os != "mac" || debug || !nightly_build
[browser_dbg_rr_breakpoints-02.js]
skip-if = os != "mac" || debug || !nightly_build
[browser_dbg_rr_breakpoints-03.js]
skip-if = os != "mac" || debug || !nightly_build
[browser_dbg_rr_breakpoints-04.js]
skip-if = os != "mac" || debug || !nightly_build
[browser_dbg_rr_breakpoints-05.js]
skip-if = os != "mac" || debug || !nightly_build
[browser_dbg_rr_record.js]
skip-if = os != "mac" || debug || !nightly_build
[browser_dbg_rr_stepping-01.js]
skip-if = os != "mac" || debug || !nightly_build
[browser_dbg_rr_stepping-02.js]
skip-if = os != "mac" || debug || !nightly_build
[browser_dbg_rr_stepping-03.js]
skip-if = os != "mac" || debug || !nightly_build
[browser_dbg_rr_stepping-04.js]
skip-if = os != "mac" || debug || !nightly_build

View file

@ -0,0 +1,29 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Test unhandled divergence while evaluating at a breakpoint with Web Replay.
async function test() {
waitForExplicitFinish();
let tab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
gBrowser.selectedTab = tab;
openTrustedLinkIn(EXAMPLE_URL + "doc_rr_basic.html", "current");
await once(Services.ppmm, "RecordingFinished");
let toolbox = await attachDebugger(tab), client = toolbox.threadClient;
await client.interrupt();
await setBreakpoint(client, "doc_rr_basic.html", 21);
await rewindToLine(client, 21);
await checkEvaluateInTopFrame(client, "number", 10);
await checkEvaluateInTopFrameThrows(client, "window.alert(3)");
await checkEvaluateInTopFrame(client, "number", 10);
await checkEvaluateInTopFrameThrows(client, "window.alert(3)");
await checkEvaluateInTopFrame(client, "number", 10);
await checkEvaluateInTopFrame(client, "testStepping2()", undefined);
await toolbox.destroy();
await gBrowser.removeTab(tab);
finish();
}

View file

@ -0,0 +1,29 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Test some issues when stepping around after hitting a breakpoint while recording.
async function test() {
waitForExplicitFinish();
let tab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
gBrowser.selectedTab = tab;
openTrustedLinkIn(EXAMPLE_URL + "doc_rr_continuous.html", "current");
let toolbox = await attachDebugger(tab), client = toolbox.threadClient;
await client.interrupt();
await setBreakpoint(client, "doc_rr_continuous.html", 19);
await resumeToLine(client, 19);
await reverseStepOverToLine(client, 18);
await checkEvaluateInTopFrame(client, "SpecialPowers.Cu.recordReplayDirective(/* AlwaysTakeTemporarySnapshots */ 3)", undefined);
await stepInToLine(client, 22);
await setBreakpoint(client, "doc_rr_continuous.html", 24);
await resumeToLine(client, 24);
await setBreakpoint(client, "doc_rr_continuous.html", 22);
await rewindToLine(client, 22);
await toolbox.destroy();
await gBrowser.removeTab(tab);
finish();
}

View file

@ -0,0 +1,36 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Test navigating back to earlier breakpoints while recording, then resuming
// recording.
async function test() {
waitForExplicitFinish();
let tab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
gBrowser.selectedTab = tab;
openTrustedLinkIn(EXAMPLE_URL + "doc_rr_continuous.html", "current");
let toolbox = await attachDebugger(tab), client = toolbox.threadClient;
await client.interrupt();
await setBreakpoint(client, "doc_rr_continuous.html", 14);
await resumeToLine(client, 14);
let value = await evaluateInTopFrame(client, "number");
await resumeToLine(client, 14);
await checkEvaluateInTopFrame(client, "number", value + 1);
await rewindToLine(client, 14);
await checkEvaluateInTopFrame(client, "number", value);
await resumeToLine(client, 14);
await checkEvaluateInTopFrame(client, "number", value + 1);
await resumeToLine(client, 14);
await checkEvaluateInTopFrame(client, "number", value + 2);
await resumeToLine(client, 14);
await checkEvaluateInTopFrame(client, "number", value + 3);
await rewindToLine(client, 14);
await checkEvaluateInTopFrame(client, "number", value + 2);
await toolbox.destroy();
await gBrowser.removeTab(tab);
finish();
}

View file

@ -0,0 +1,31 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Test hitting breakpoints when rewinding past the point where the breakpoint
// script was created.
async function test() {
waitForExplicitFinish();
let tab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
gBrowser.selectedTab = tab;
openTrustedLinkIn(EXAMPLE_URL + "doc_rr_basic.html", "current");
await once(Services.ppmm, "RecordingFinished");
let toolbox = await attachDebugger(tab), client = toolbox.threadClient;
await client.interrupt();
// Rewind to the beginning of the recording.
await rewindToLine(client, undefined);
await setBreakpoint(client, "doc_rr_basic.html", 21);
await resumeToLine(client, 21);
await checkEvaluateInTopFrame(client, "number", 1);
await resumeToLine(client, 21);
await checkEvaluateInTopFrame(client, "number", 2);
await toolbox.destroy();
await gBrowser.removeTab(tab);
finish();
}

View file

@ -0,0 +1,19 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Test basic recording of a tab without any debugging.
async function test() {
waitForExplicitFinish();
var recordingTab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
gBrowser.selectedTab = recordingTab;
openTrustedLinkIn(EXAMPLE_URL + "doc_rr_basic.html", "current");
await once(Services.ppmm, "RecordingFinished");
await gBrowser.removeTab(recordingTab);
ok(true, "Finished");
finish();
}

View file

@ -0,0 +1,29 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Test basic step-over/back functionality in web replay.
async function test() {
waitForExplicitFinish();
let tab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
gBrowser.selectedTab = tab;
openTrustedLinkIn(EXAMPLE_URL + "doc_rr_basic.html", "current");
await once(Services.ppmm, "RecordingFinished");
let toolbox = await attachDebugger(tab), client = toolbox.threadClient;
await client.interrupt();
await setBreakpoint(client, "doc_rr_basic.html", 21);
await rewindToLine(client, 21);
await checkEvaluateInTopFrame(client, "number", 10);
await reverseStepOverToLine(client, 20);
await checkEvaluateInTopFrame(client, "number", 9);
await checkEvaluateInTopFrameThrows(client, "window.alert(3)");
await stepOverToLine(client, 21);
await checkEvaluateInTopFrame(client, "number", 10);
await toolbox.destroy();
await gBrowser.removeTab(tab);
finish();
}

View file

@ -0,0 +1,30 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Test fixes for some simple stepping bugs.
async function test() {
waitForExplicitFinish();
let tab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
gBrowser.selectedTab = tab;
openTrustedLinkIn(EXAMPLE_URL + "doc_rr_basic.html", "current");
await once(Services.ppmm, "RecordingFinished");
let toolbox = await attachDebugger(tab), client = toolbox.threadClient;
await client.interrupt();
await setBreakpoint(client, "doc_rr_basic.html", 22);
await rewindToLine(client, 22);
await stepInToLine(client, 25);
await stepOverToLine(client, 26);
await stepOverToLine(client, 27);
await reverseStepInToLine(client, 33);
await reverseStepOverToLine(client, 32);
await reverseStepOutToLine(client, 26);
await reverseStepOverToLine(client, 25);
await toolbox.destroy();
await gBrowser.removeTab(tab);
finish();
}

View file

@ -0,0 +1,28 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Test stepping back while recording, then resuming recording.
async function test() {
waitForExplicitFinish();
let tab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
gBrowser.selectedTab = tab;
openTrustedLinkIn(EXAMPLE_URL + "doc_rr_continuous.html", "current");
let toolbox = await attachDebugger(tab), client = toolbox.threadClient;
await client.interrupt();
await setBreakpoint(client, "doc_rr_continuous.html", 13);
await resumeToLine(client, 13);
let value = await evaluateInTopFrame(client, "number");
await reverseStepOverToLine(client, 12);
await checkEvaluateInTopFrame(client, "number", value - 1);
await resumeToLine(client, 13);
await resumeToLine(client, 13);
await checkEvaluateInTopFrame(client, "number", value + 1);
await toolbox.destroy();
await gBrowser.removeTab(tab);
finish();
}

View file

@ -0,0 +1,45 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Stepping past the beginning or end of a frame should act like a step-out.
async function test() {
waitForExplicitFinish();
let tab = BrowserTestUtils.addTab(gBrowser, null, { recordExecution: "*" });
gBrowser.selectedTab = tab;
openTrustedLinkIn(EXAMPLE_URL + "doc_rr_basic.html", "current");
await once(Services.ppmm, "RecordingFinished");
let toolbox = await attachDebugger(tab), client = toolbox.threadClient;
await client.interrupt();
await setBreakpoint(client, "doc_rr_basic.html", 21);
await rewindToLine(client, 21);
await checkEvaluateInTopFrame(client, "number", 10);
await reverseStepOverToLine(client, 20);
await reverseStepOverToLine(client, 12);
// After reverse-stepping out of the topmost frame we should rewind to the
// last breakpoint hit.
await reverseStepOverToLine(client, 21);
await checkEvaluateInTopFrame(client, "number", 9);
await stepOverToLine(client, 22);
await stepOverToLine(client, 23);
// Line 13 seems like it should be the next stepping point, but the column
// numbers reported by the JS engine and required by the pause points do not
// match, and we don't stop here.
//await stepOverToLine(client, 13);
await stepOverToLine(client, 17);
await stepOverToLine(client, 18);
// After forward-stepping out of the topmost frame we should run forward to
// the next breakpoint hit.
await stepOverToLine(client, 21);
await checkEvaluateInTopFrame(client, "number", 10);
await toolbox.destroy();
await gBrowser.removeTab(tab);
finish();
}

View file

@ -0,0 +1,28 @@
<html lang="en" dir="ltr">
<body>
<div id="maindiv">Hello World!</div>
</body>
<script>
var number = 0;
function f() {
updateNumber();
window.setTimeout(f, 1);
}
function updateNumber() {
number++;
document.getElementById("maindiv").innerHTML = "Number: " + number;
testStepping();
}
function testStepping() {
var a = 0;
testStepping2();
return a;
}
function testStepping2() {
var c = 0;
c++;
c--;
}
window.setTimeout(f, 100);
</script>
</html>

View file

@ -3207,10 +3207,21 @@ nsFocusManager::IsHostOrSlot(nsIContent* aContent)
} }
int32_t int32_t
nsFocusManager::HostOrSlotTabIndexValue(nsIContent* aContent) nsFocusManager::HostOrSlotTabIndexValue(nsIContent* aContent,
bool* aIsFocusable)
{ {
MOZ_ASSERT(IsHostOrSlot(aContent)); MOZ_ASSERT(IsHostOrSlot(aContent));
if (aIsFocusable) {
*aIsFocusable = false;
nsIFrame* frame = aContent->GetPrimaryFrame();
if (frame) {
int32_t tabIndex;
frame->IsFocusable(&tabIndex, 0);
*aIsFocusable = tabIndex >= 0;
}
}
const nsAttrValue* attrVal = const nsAttrValue* attrVal =
aContent->AsElement()->GetParsedAttr(nsGkAtoms::tabindex); aContent->AsElement()->GetParsedAttr(nsGkAtoms::tabindex);
if (!attrVal) { if (!attrVal) {
@ -3673,8 +3684,12 @@ nsFocusManager::GetNextTabbableContent(nsIPresShell* aPresShell,
// hosts and slots are handled before other elements. // hosts and slots are handled before other elements.
if (currentContent && nsDocument::IsShadowDOMEnabled(currentContent) && if (currentContent && nsDocument::IsShadowDOMEnabled(currentContent) &&
IsHostOrSlot(currentContent)) { IsHostOrSlot(currentContent)) {
int32_t tabIndex = HostOrSlotTabIndexValue(currentContent); bool focusableHostSlot;
if (tabIndex >= 0 && int32_t tabIndex = HostOrSlotTabIndexValue(currentContent,
&focusableHostSlot);
// Host or slot itself isn't focusable, enter its scope.
if (!focusableHostSlot &&
tabIndex >= 0 &&
(aIgnoreTabIndex || aCurrentTabIndex == tabIndex)) { (aIgnoreTabIndex || aCurrentTabIndex == tabIndex)) {
nsIContent* contentToFocus = nsIContent* contentToFocus =
GetNextTabbableContentInScope(currentContent, currentContent, GetNextTabbableContentInScope(currentContent, currentContent,

View file

@ -453,8 +453,11 @@ protected:
* Host and Slot elements need to be handled as if they had tabindex 0 even * Host and Slot elements need to be handled as if they had tabindex 0 even
* when they don't have the attribute. This is a helper method to get the right * when they don't have the attribute. This is a helper method to get the right
* value for focus navigation. * value for focus navigation.
* If aIsFocusable is passed, it is set to true if the element itself is
* focusable.
*/ */
int32_t HostOrSlotTabIndexValue(nsIContent* aContent); int32_t HostOrSlotTabIndexValue(nsIContent* aContent,
bool* aIsFocusable = nullptr);
/** /**
* Retrieve the next tabbable element in scope owned by aOwner, using * Retrieve the next tabbable element in scope owned by aOwner, using

View file

@ -6255,6 +6255,38 @@ nsGlobalWindowInner::GetParentInternal()
return outer->GetParentInternal(); return outer->GetParentInternal();
} }
nsIPrincipal*
nsGlobalWindowInner::GetTopLevelPrincipal()
{
nsPIDOMWindowOuter* outerWindow = GetOuterWindowInternal();
if (!outerWindow) {
return nullptr;
}
nsPIDOMWindowOuter* topLevelOuterWindow = GetTopInternal();
if (!topLevelOuterWindow) {
return nullptr;
}
if (topLevelOuterWindow == outerWindow) {
return nullptr;
}
nsPIDOMWindowInner* topLevelInnerWindow =
topLevelOuterWindow->GetCurrentInnerWindow();
if (NS_WARN_IF(!topLevelInnerWindow)) {
return nullptr;
}
nsIPrincipal* topLevelPrincipal =
nsGlobalWindowInner::Cast(topLevelInnerWindow)->GetPrincipal();
if (NS_WARN_IF(!topLevelPrincipal)) {
return nullptr;
}
return topLevelPrincipal;
}
nsIPrincipal* nsIPrincipal*
nsGlobalWindowInner::GetTopLevelStorageAreaPrincipal() nsGlobalWindowInner::GetTopLevelStorageAreaPrincipal()
{ {

View file

@ -1212,7 +1212,12 @@ public:
public: public:
virtual already_AddRefed<nsPIWindowRoot> GetTopWindowRoot() override; virtual already_AddRefed<nsPIWindowRoot> GetTopWindowRoot() override;
// Get the parent principal, returns null if this is a toplevel window. // Get the toplevel principal, returns null if this is a toplevel window.
nsIPrincipal* GetTopLevelPrincipal();
// Get the parent principal, returns null if this or the parent are not a
// toplevel window. This is mainly used to determine the anti-tracking storage
// area.
nsIPrincipal* GetTopLevelStorageAreaPrincipal(); nsIPrincipal* GetTopLevelStorageAreaPrincipal();
protected: protected:

View file

@ -306,6 +306,56 @@
p.remove(); p.remove();
} }
function testFocusableHost() {
opener.is(document.activeElement, document.body.firstChild,
"body's first child should have focus.");
var host = document.createElement("div");
host.id = "host";
host.tabIndex = 0;
host.onfocus = focusLogger;
document.body.appendChild(host);
var slotted = document.createElement("div");
slotted.tabIndex = 0;
slotted.onfocus = focusLogger;
host.appendChild(slotted);
var sr0 = host.attachShadow({mode: "open"});
sr0.appendChild(document.createElement("slot"));
var p = document.createElement("p");
p.innerHTML = " <a href='#p'>link 1</a> ";
var a = p.firstElementChild;
a.onfocus = focusLogger;
document.body.appendChild(p);
document.body.offsetLeft;
synthesizeKey("KEY_Tab");
opener.is(lastFocusTarget, host, "Should have focused host.");
synthesizeKey("KEY_Tab");
opener.is(lastFocusTarget, slotted, "Should have focused slotted.");
synthesizeKey("KEY_Tab");
opener.is(lastFocusTarget, a, "Should have focused a.");
// Backwards
synthesizeKey("KEY_Tab", {shiftKey: true});
opener.is(lastFocusTarget, slotted, "Should have focused slotted.");
synthesizeKey("KEY_Tab", {shiftKey: true});
opener.is(lastFocusTarget, host, "Should have focused host.");
synthesizeKey("KEY_Tab", {shiftKey: true});
opener.is(document.activeElement, document.body.firstChild,
"body's first child should have focus.");
host.remove();
p.remove();
}
function runTest() { function runTest() {
testTabbingThroughShadowDOMWithTabIndexes(); testTabbingThroughShadowDOMWithTabIndexes();
@ -313,6 +363,7 @@
testTabbingThroughNestedShadowDOM(); testTabbingThroughNestedShadowDOM();
testTabbingThroughDisplayContentsHost(); testTabbingThroughDisplayContentsHost();
testTabbingThroughLightDOMShadowDOMLightDOM(); testTabbingThroughLightDOMShadowDOMLightDOM();
testFocusableHost();
opener.didRunTests(); opener.didRunTests();
window.close(); window.close();

View file

@ -12,4 +12,5 @@ support-files =
subsuite = gpu subsuite = gpu
[test_webgl_crossorigin_textures.html] [test_webgl_crossorigin_textures.html]
subsuite = gpu subsuite = gpu
skip-if = android_version == '24'

View file

@ -19,6 +19,7 @@
#include "mozilla/Logging.h" #include "mozilla/Logging.h"
#include "mozilla/media/MediaUtils.h" #include "mozilla/media/MediaUtils.h"
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
#include "mozilla/StaticPrefs.h"
#include "mozilla/StaticPtr.h" #include "mozilla/StaticPtr.h"
#include "mozilla/TaskQueue.h" #include "mozilla/TaskQueue.h"
#include "mozilla/Unused.h" #include "mozilla/Unused.h"
@ -1057,7 +1058,7 @@ MediaEncoder::Stop()
bool bool
MediaEncoder::IsWebMEncoderEnabled() MediaEncoder::IsWebMEncoderEnabled()
{ {
return Preferences::GetBool("media.encoder.webm.enabled"); return StaticPrefs::MediaEncoderWebMEnabled();
} }
#endif #endif

View file

@ -407,7 +407,7 @@ MediaCapabilities::DecodingInfo(
WorkerPrivate* wp = GetCurrentThreadWorkerPrivate(); WorkerPrivate* wp = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(wp, "Must be called from a worker thread"); MOZ_ASSERT(wp, "Must be called from a worker thread");
targetThread = wp->HybridEventTarget(); targetThread = wp->HybridEventTarget();
RefPtr<StrongWorkerRef> strongWorkerRef = StrongWorkerRef::Create( workerRef = StrongWorkerRef::Create(
wp, "MediaCapabilities", [holder, targetThread]() { wp, "MediaCapabilities", [holder, targetThread]() {
MOZ_ASSERT(targetThread->IsOnCurrentThread()); MOZ_ASSERT(targetThread->IsOnCurrentThread());
holder->DisconnectIfExists(); holder->DisconnectIfExists();

View file

@ -273,12 +273,14 @@ skip-if = toolkit == 'android' # bug 1054087
skip-if = os == 'android' skip-if = os == 'android'
[test_handle_new_lines.html] [test_handle_new_lines.html]
subsuite = clipboard subsuite = clipboard
skip-if = android_version == '24'
[test_inline_style_cache.html] [test_inline_style_cache.html]
[test_inlineTableEditing.html] [test_inlineTableEditing.html]
[test_insertParagraph_in_inline_editing_host.html] [test_insertParagraph_in_inline_editing_host.html]
[test_keypress_untrusted_event.html] [test_keypress_untrusted_event.html]
[test_middle_click_paste.html] [test_middle_click_paste.html]
subsuite = clipboard subsuite = clipboard
skip-if = android_version == '24'
[test_objectResizing.html] [test_objectResizing.html]
[test_root_element_replacement.html] [test_root_element_replacement.html]
[test_select_all_without_body.html] [test_select_all_without_body.html]

View file

@ -0,0 +1,76 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#include "MemoryPressureObserver.h"
namespace mozilla {
namespace layers {
MemoryPressureObserver::MemoryPressureObserver(MemoryPressureListener* aListener)
: mListener(aListener)
{}
MemoryPressureObserver::~MemoryPressureObserver()
{
// If this assertion is hit we probably forgot to unregister the observer.
MOZ_ASSERT(!mListener);
}
already_AddRefed<MemoryPressureObserver>
MemoryPressureObserver::Create(MemoryPressureListener* aListener)
{
nsCOMPtr<nsIObserverService> service = services::GetObserverService();
if (!service) {
return nullptr;
}
RefPtr<MemoryPressureObserver> observer = new MemoryPressureObserver(aListener);
bool useWeakRef = false;
service->AddObserver(observer, "memory-pressure", useWeakRef);
return observer.forget();
}
void
MemoryPressureObserver::Unregister()
{
if (!mListener) {
return;
}
nsCOMPtr<nsIObserverService> service = services::GetObserverService();
if (service) {
service->RemoveObserver(this, "memory-pressure");
}
mListener = nullptr;
}
NS_IMETHODIMP
MemoryPressureObserver::Observe(nsISupports* aSubject,
const char* aTopic,
const char16_t* aData)
{
if (mListener && strcmp(aTopic, "memory-pressure")) {
MemoryPressureReason reason = MemoryPressureReason::LOW_MEMORY;
auto reason_string = nsDependentString(aData);
if (StringBeginsWith(reason_string, NS_LITERAL_STRING("low-memory-ongoing"))) {
reason = MemoryPressureReason::LOW_MEMORY_ONGOING;
} else if (StringBeginsWith(reason_string, NS_LITERAL_STRING("heap-minimize"))) {
reason = MemoryPressureReason::HEAP_MINIMIZE;
}
mListener->OnMemoryPressure(reason);
}
return NS_OK;
}
NS_IMPL_ISUPPORTS(MemoryPressureObserver, nsIObserver)
} // namespace layers
} // namespace mozilla

View file

@ -0,0 +1,59 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* 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/. */
#ifndef MOZILLA_LAYERS_MEMORYPRESSUREOBSERVER_H
#define MOZILLA_LAYERS_MEMORYPRESSUREOBSERVER_H
#include "nsIObserver.h"
namespace mozilla {
namespace layers {
// A simple memory pressure observer implementation born out of the realization
// that almost all of our memory pressure observers do exactly the same thing.
//
// The intended way to use it is to have the class that nees to react on memory
// pressure inherit the MemoryPressureListener interface and own a strong
// reference to a MemoryPressureListener object.
// Call Unregister on the listener in the destructor of your class or whenever
// you do not which to receive the notification anymore, otherwise the listener
// will be held alive by the observer service (leak) and keep a dangling pointer
// to your class.
/// See nsIMemory.idl
enum class MemoryPressureReason {
LOW_MEMORY,
LOW_MEMORY_ONGOING,
HEAP_MINIMIZE,
};
class MemoryPressureListener {
public:
virtual void OnMemoryPressure(MemoryPressureReason aWhy) = 0;
};
class MemoryPressureObserver final : public nsIObserver {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
// Returns null if anything goes wrong.
static already_AddRefed<MemoryPressureObserver>
Create(MemoryPressureListener* aListener);
void Unregister();
private:
explicit MemoryPressureObserver(MemoryPressureListener* aListener);
virtual ~MemoryPressureObserver();
MemoryPressureListener* mListener;
};
} // namespace layers
} // namespace mozilla
#endif

View file

@ -9,8 +9,13 @@
#include "GLContext.h" // for GLContext #include "GLContext.h" // for GLContext
#include "GLScreenBuffer.h" // for GLScreenBuffer #include "GLScreenBuffer.h" // for GLScreenBuffer
#include "SharedSurfaceGL.h" // for SurfaceFactory_GLTexture, etc #include "SharedSurfaceGL.h" // for SurfaceFactory_GLTexture, etc
#include "gfxUtils.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/layers/AsyncCanvasRenderer.h" #include "mozilla/layers/AsyncCanvasRenderer.h"
#include "mozilla/layers/TextureClientSharedSurface.h" #include "mozilla/layers/TextureClientSharedSurface.h"
#include "mozilla/layers/CompositableForwarder.h"
using namespace mozilla::gfx;
namespace mozilla { namespace mozilla {
namespace layers { namespace layers {

View file

@ -16,6 +16,10 @@ namespace gl {
class SurfaceFactory; class SurfaceFactory;
} // namespace gl } // namespace gl
namespace gfx {
class DrawTarget;
} // namespace gfx
namespace layers { namespace layers {
class ShareableCanvasRenderer : public CopyableCanvasRenderer class ShareableCanvasRenderer : public CopyableCanvasRenderer

View file

@ -45,52 +45,6 @@ namespace layers {
using namespace mozilla::gfx; using namespace mozilla::gfx;
void
ClientLayerManager::MemoryPressureObserver::Destroy()
{
UnregisterMemoryPressureEvent();
mClientLayerManager = nullptr;
}
NS_IMETHODIMP
ClientLayerManager::MemoryPressureObserver::Observe(nsISupports* aSubject,
const char* aTopic,
const char16_t* aSomeData)
{
if (!mClientLayerManager || strcmp(aTopic, "memory-pressure")) {
return NS_OK;
}
mClientLayerManager->HandleMemoryPressure();
return NS_OK;
}
void
ClientLayerManager::MemoryPressureObserver::RegisterMemoryPressureEvent()
{
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
MOZ_ASSERT(observerService);
if (observerService) {
observerService->AddObserver(this, "memory-pressure", false);
}
}
void
ClientLayerManager::MemoryPressureObserver::UnregisterMemoryPressureEvent()
{
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (observerService) {
observerService->RemoveObserver(this, "memory-pressure");
}
}
NS_IMPL_ISUPPORTS(ClientLayerManager::MemoryPressureObserver, nsIObserver)
ClientLayerManager::ClientLayerManager(nsIWidget* aWidget) ClientLayerManager::ClientLayerManager(nsIWidget* aWidget)
: mPhase(PHASE_NONE) : mPhase(PHASE_NONE)
, mWidget(aWidget) , mWidget(aWidget)
@ -109,13 +63,13 @@ ClientLayerManager::ClientLayerManager(nsIWidget* aWidget)
, mForwarder(new ShadowLayerForwarder(this)) , mForwarder(new ShadowLayerForwarder(this))
{ {
MOZ_COUNT_CTOR(ClientLayerManager); MOZ_COUNT_CTOR(ClientLayerManager);
mMemoryPressureObserver = new MemoryPressureObserver(this); mMemoryPressureObserver = MemoryPressureObserver::Create(this);
} }
ClientLayerManager::~ClientLayerManager() ClientLayerManager::~ClientLayerManager()
{ {
mMemoryPressureObserver->Destroy(); mMemoryPressureObserver->Unregister();
ClearCachedResources(); ClearCachedResources();
// Stop receiveing AsyncParentMessage at Forwarder. // Stop receiveing AsyncParentMessage at Forwarder.
// After the call, the message is directly handled by LayerTransactionChild. // After the call, the message is directly handled by LayerTransactionChild.
@ -875,7 +829,7 @@ ClientLayerManager::ClearCachedResources(Layer* aSubtree)
} }
void void
ClientLayerManager::HandleMemoryPressure() ClientLayerManager::OnMemoryPressure(MemoryPressureReason aWhy)
{ {
if (mRoot) { if (mRoot) {
HandleMemoryPressureLayer(mRoot); HandleMemoryPressureLayer(mRoot);

View file

@ -21,6 +21,7 @@
#include "mozilla/layers/PaintThread.h" // For PaintThread #include "mozilla/layers/PaintThread.h" // For PaintThread
#include "mozilla/layers/ShadowLayers.h" // for ShadowLayerForwarder, etc #include "mozilla/layers/ShadowLayers.h" // for ShadowLayerForwarder, etc
#include "mozilla/layers/APZTestData.h" // for APZTestData #include "mozilla/layers/APZTestData.h" // for APZTestData
#include "mozilla/layers/MemoryPressureObserver.h"
#include "nsCOMPtr.h" // for already_AddRefed #include "nsCOMPtr.h" // for already_AddRefed
#include "nsIObserver.h" // for nsIObserver #include "nsIObserver.h" // for nsIObserver
#include "nsISupportsImpl.h" // for Layer::Release, etc #include "nsISupportsImpl.h" // for Layer::Release, etc
@ -47,6 +48,7 @@ class ImageLayer;
class FrameUniformityData; class FrameUniformityData;
class ClientLayerManager final : public LayerManager class ClientLayerManager final : public LayerManager
, public MemoryPressureListener
{ {
typedef nsTArray<RefPtr<Layer> > LayerRefArray; typedef nsTArray<RefPtr<Layer> > LayerRefArray;
@ -149,7 +151,7 @@ public:
// if we have one. // if we have one.
virtual void ClearCachedResources(Layer* aSubtree = nullptr) override; virtual void ClearCachedResources(Layer* aSubtree = nullptr) override;
void HandleMemoryPressure(); virtual void OnMemoryPressure(MemoryPressureReason aWhy) override;
void SetRepeatTransaction() { mRepeatTransaction = true; } void SetRepeatTransaction() { mRepeatTransaction = true; }
bool GetRepeatTransaction() { return mRepeatTransaction; } bool GetRepeatTransaction() { return mRepeatTransaction; }
@ -267,29 +269,6 @@ protected:
TransactionPhase mPhase; TransactionPhase mPhase;
private: private:
// Listen memory-pressure event for ClientLayerManager
class MemoryPressureObserver final : public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
explicit MemoryPressureObserver(ClientLayerManager* aClientLayerManager)
: mClientLayerManager(aClientLayerManager)
{
RegisterMemoryPressureEvent();
}
void Destroy();
private:
virtual ~MemoryPressureObserver() {}
void RegisterMemoryPressureEvent();
void UnregisterMemoryPressureEvent();
ClientLayerManager* mClientLayerManager;
};
/** /**
* Forward transaction results to the parent context. * Forward transaction results to the parent context.
*/ */

View file

@ -2354,6 +2354,14 @@ CompositorBridgeParent::NotifyWebRenderError(wr::WebRenderError aError)
Unused << SendNotifyWebRenderError(aError); Unused << SendNotifyWebRenderError(aError);
} }
void
CompositorBridgeParent::NotifyWebRenderContextPurge()
{
MOZ_ASSERT(CompositorLoop() == MessageLoop::current());
RefPtr<wr::WebRenderAPI> api = mWrBridge->GetWebRenderAPI();
api->ClearAllCaches();
}
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
//#define PLUGINS_LOG(...) printf_stderr("CP [%s]: ", __FUNCTION__); //#define PLUGINS_LOG(...) printf_stderr("CP [%s]: ", __FUNCTION__);
// printf_stderr(__VA_ARGS__); // printf_stderr(__VA_ARGS__);

View file

@ -274,6 +274,7 @@ public:
bool IsSameProcess() const override; bool IsSameProcess() const override;
void NotifyWebRenderError(wr::WebRenderError aError); void NotifyWebRenderError(wr::WebRenderError aError);
void NotifyWebRenderContextPurge();
void NotifyPipelineRendered(const wr::PipelineId& aPipelineId, void NotifyPipelineRendered(const wr::PipelineId& aPipelineId,
const wr::Epoch& aEpoch, const wr::Epoch& aEpoch,
TimeStamp& aCompositeStart, TimeStamp& aCompositeStart,

View file

@ -30,20 +30,39 @@ public:
ImageKeyData(ImageKeyData&& aOther) ImageKeyData(ImageKeyData&& aOther)
: mManager(std::move(aOther.mManager)) : mManager(std::move(aOther.mManager))
, mDirtyRect(std::move(aOther.mDirtyRect))
, mImageKey(aOther.mImageKey) , mImageKey(aOther.mImageKey)
{ } { }
ImageKeyData& operator=(ImageKeyData&& aOther) ImageKeyData& operator=(ImageKeyData&& aOther)
{ {
mManager = std::move(aOther.mManager); mManager = std::move(aOther.mManager);
mDirtyRect = std::move(aOther.mDirtyRect);
mImageKey = aOther.mImageKey; mImageKey = aOther.mImageKey;
return *this; return *this;
} }
void MergeDirtyRect(const Maybe<IntRect>& aDirtyRect)
{
if (mDirtyRect) {
if (aDirtyRect) {
mDirtyRect->UnionRect(mDirtyRect.ref(), aDirtyRect.ref());
}
} else {
mDirtyRect = aDirtyRect;
}
}
Maybe<IntRect> TakeDirtyRect()
{
return std::move(mDirtyRect);
}
ImageKeyData(const ImageKeyData&) = delete; ImageKeyData(const ImageKeyData&) = delete;
ImageKeyData& operator=(const ImageKeyData&) = delete; ImageKeyData& operator=(const ImageKeyData&) = delete;
RefPtr<WebRenderLayerManager> mManager; RefPtr<WebRenderLayerManager> mManager;
Maybe<IntRect> mDirtyRect;
wr::ImageKey mImageKey; wr::ImageKey mImageKey;
}; };
@ -143,14 +162,23 @@ public:
bool ownsKey = wrBridge->GetNamespace() == entry.mImageKey.mNamespace; bool ownsKey = wrBridge->GetNamespace() == entry.mImageKey.mNamespace;
if (!ownsKey) { if (!ownsKey) {
entry.mImageKey = wrBridge->GetNextImageKey(); entry.mImageKey = wrBridge->GetNextImageKey();
entry.TakeDirtyRect();
aResources.AddExternalImage(mId, entry.mImageKey); aResources.AddExternalImage(mId, entry.mImageKey);
} else if (aDirtyRect) { } else {
aResources.UpdateExternalImage(mId, entry.mImageKey, entry.MergeDirtyRect(aDirtyRect);
ViewAs<ImagePixel>(aDirtyRect.ref())); Maybe<IntRect> dirtyRect = entry.TakeDirtyRect();
if (dirtyRect) {
aResources.UpdateExternalImage(mId, entry.mImageKey,
ViewAs<ImagePixel>(dirtyRect.ref()));
}
} }
key = entry.mImageKey; key = entry.mImageKey;
found = true; found = true;
} else {
// We don't have the resource update queue for this manager, so just
// accumulate the dirty rects until it is requested.
entry.MergeDirtyRect(aDirtyRect);
} }
} }
@ -316,7 +344,7 @@ SharedSurfacesChild::Share(SourceSurfaceSharedData* aSurface,
// Each time the surface changes, the producers of SourceSurfaceSharedData // Each time the surface changes, the producers of SourceSurfaceSharedData
// surfaces promise to increment the invalidation counter each time the // surfaces promise to increment the invalidation counter each time the
// surface has changed. We can use this counter to determine whether or not // surface has changed. We can use this counter to determine whether or not
// we should upate our paired ImageKey. // we should update our paired ImageKey.
Maybe<IntRect> dirtyRect = aSurface->TakeDirtyRect(); Maybe<IntRect> dirtyRect = aSurface->TakeDirtyRect();
SharedUserData* data = nullptr; SharedUserData* data = nullptr;
nsresult rv = SharedSurfacesChild::ShareInternal(aSurface, &data); nsresult rv = SharedSurfacesChild::ShareInternal(aSurface, &data);

View file

@ -208,6 +208,7 @@ EXPORTS.mozilla.layers += [
'LayerMetricsWrapper.h', 'LayerMetricsWrapper.h',
'LayersHelpers.h', 'LayersHelpers.h',
'LayersTypes.h', 'LayersTypes.h',
'MemoryPressureObserver.h',
'mlgpu/LayerManagerMLGPU.h', 'mlgpu/LayerManagerMLGPU.h',
'mlgpu/LayerMLGPU.h', 'mlgpu/LayerMLGPU.h',
'mlgpu/MemoryReportingMLGPU.h', 'mlgpu/MemoryReportingMLGPU.h',
@ -440,6 +441,7 @@ UNIFIED_SOURCES += [
'LayerSorter.cpp', 'LayerSorter.cpp',
'LayersTypes.cpp', 'LayersTypes.cpp',
'LayerTreeInvalidation.cpp', 'LayerTreeInvalidation.cpp',
'MemoryPressureObserver.cpp',
'mlgpu/BufferCache.cpp', 'mlgpu/BufferCache.cpp',
'mlgpu/CanvasLayerMLGPU.cpp', 'mlgpu/CanvasLayerMLGPU.cpp',
'mlgpu/ContainerLayerMLGPU.cpp', 'mlgpu/ContainerLayerMLGPU.cpp',

View file

@ -464,28 +464,13 @@ FontPrefChanged(const char* aPref, void* aData)
gfxPlatform::GetPlatform()->FontsPrefsChanged(aPref); gfxPlatform::GetPlatform()->FontsPrefsChanged(aPref);
} }
class MemoryPressureObserver final : public nsIObserver void
gfxPlatform::OnMemoryPressure(layers::MemoryPressureReason aWhy)
{ {
~MemoryPressureObserver() = default;
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
};
NS_IMPL_ISUPPORTS(MemoryPressureObserver, nsIObserver)
NS_IMETHODIMP
MemoryPressureObserver::Observe(nsISupports *aSubject,
const char *aTopic,
const char16_t *someData)
{
NS_ASSERTION(strcmp(aTopic, "memory-pressure") == 0, "unexpected event topic");
Factory::PurgeAllCaches(); Factory::PurgeAllCaches();
gfxGradientCache::PurgeAllCaches(); gfxGradientCache::PurgeAllCaches();
PurgeSkiaFontCache();
gfxPlatform::PurgeSkiaFontCache(); PurgeSkiaGPUCache();
gfxPlatform::GetPlatform()->PurgeSkiaGPUCache();
return NS_OK;
} }
gfxPlatform::gfxPlatform() gfxPlatform::gfxPlatform()
@ -819,11 +804,7 @@ gfxPlatform::Init()
CreateCMSOutputProfile(); CreateCMSOutputProfile();
// Listen to memory pressure event so we can purge DrawTarget caches // Listen to memory pressure event so we can purge DrawTarget caches
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); gPlatform->mMemoryPressureObserver = layers::MemoryPressureObserver::Create(gPlatform);
if (obs) {
gPlatform->mMemoryPressureObserver = new MemoryPressureObserver();
obs->AddObserver(gPlatform->mMemoryPressureObserver, "memory-pressure", false);
}
// Request the imgITools service, implicitly initializing ImageLib. // Request the imgITools service, implicitly initializing ImageLib.
nsCOMPtr<imgITools> imgTools = do_GetService("@mozilla.org/image/tools;1"); nsCOMPtr<imgITools> imgTools = do_GetService("@mozilla.org/image/tools;1");
@ -872,6 +853,7 @@ gfxPlatform::Init()
gfxUtils::RemoveShaderCacheFromDiskIfNecessary(); gfxUtils::RemoveShaderCacheFromDiskIfNecessary();
} }
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (obs) { if (obs) {
obs->NotifyObservers(nullptr, "gfx-features-ready", nullptr); obs->NotifyObservers(nullptr, "gfx-features-ready", nullptr);
} }
@ -988,12 +970,10 @@ gfxPlatform::Shutdown()
Preferences::UnregisterPrefixCallbacks(FontPrefChanged, kObservedPrefs); Preferences::UnregisterPrefixCallbacks(FontPrefChanged, kObservedPrefs);
NS_ASSERTION(gPlatform->mMemoryPressureObserver, "mMemoryPressureObserver has already gone"); NS_ASSERTION(gPlatform->mMemoryPressureObserver, "mMemoryPressureObserver has already gone");
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); if (gPlatform->mMemoryPressureObserver) {
if (obs) { gPlatform->mMemoryPressureObserver->Unregister();
obs->RemoveObserver(gPlatform->mMemoryPressureObserver, "memory-pressure"); gPlatform->mMemoryPressureObserver = nullptr;
} }
gPlatform->mMemoryPressureObserver = nullptr;
gPlatform->mSkiaGlue = nullptr; gPlatform->mSkiaGlue = nullptr;
if (XRE_IsParentProcess()) { if (XRE_IsParentProcess()) {

View file

@ -26,6 +26,7 @@
#include "GfxInfoCollector.h" #include "GfxInfoCollector.h"
#include "mozilla/layers/CompositorTypes.h" #include "mozilla/layers/CompositorTypes.h"
#include "mozilla/layers/MemoryPressureObserver.h"
class gfxASurface; class gfxASurface;
class gfxFont; class gfxFont;
@ -155,7 +156,7 @@ struct BackendPrefsData
mozilla::gfx::BackendType mContentDefault = mozilla::gfx::BackendType::NONE; mozilla::gfx::BackendType mContentDefault = mozilla::gfx::BackendType::NONE;
}; };
class gfxPlatform { class gfxPlatform: public mozilla::layers::MemoryPressureListener {
friend class SRGBOverrideObserver; friend class SRGBOverrideObserver;
public: public:
@ -747,6 +748,8 @@ public:
// you probably want to use gfxVars::UseWebRender() instead of this // you probably want to use gfxVars::UseWebRender() instead of this
static bool WebRenderEnvvarEnabled(); static bool WebRenderEnvvarEnabled();
virtual void
OnMemoryPressure(mozilla::layers::MemoryPressureReason aWhy) override;
protected: protected:
gfxPlatform(); gfxPlatform();
virtual ~gfxPlatform(); virtual ~gfxPlatform();
@ -888,7 +891,7 @@ private:
RefPtr<gfxASurface> mScreenReferenceSurface; RefPtr<gfxASurface> mScreenReferenceSurface;
nsCOMPtr<nsIObserver> mSRGBOverrideObserver; nsCOMPtr<nsIObserver> mSRGBOverrideObserver;
nsCOMPtr<nsIObserver> mMemoryPressureObserver; RefPtr<mozilla::layers::MemoryPressureObserver> mMemoryPressureObserver;
// The preferred draw target backend to use for canvas // The preferred draw target backend to use for canvas
mozilla::gfx::BackendType mPreferredCanvasBackend; mozilla::gfx::BackendType mPreferredCanvasBackend;

View file

@ -95,6 +95,12 @@ RendererOGL::Update()
} }
} }
static void
DoNotifyWebRenderContextPurge(layers::CompositorBridgeParent* aBridge)
{
aBridge->NotifyWebRenderContextPurge();
}
bool bool
RendererOGL::UpdateAndRender(bool aReadback) RendererOGL::UpdateAndRender(bool aReadback)
{ {
@ -150,6 +156,18 @@ RendererOGL::UpdateAndRender(bool aReadback)
mFrameStartTime = TimeStamp(); mFrameStartTime = TimeStamp();
#endif #endif
gl::GLContext* gl = mCompositor->gl();
if (gl->IsSupported(gl::GLFeature::robustness)) {
GLenum resetStatus = gl->fGetGraphicsResetStatus();
if (resetStatus == LOCAL_GL_PURGED_CONTEXT_RESET_NV) {
layers::CompositorThreadHolder::Loop()->PostTask(NewRunnableFunction(
"DoNotifyWebRenderContextPurgeRunnable",
&DoNotifyWebRenderContextPurge,
mBridge
));
}
}
// TODO: Flush pending actions such as texture deletions/unlocks and // TODO: Flush pending actions such as texture deletions/unlocks and
// textureHosts recycling. // textureHosts recycling.

View file

@ -422,6 +422,12 @@ WebRenderAPI::Readback(const TimeStamp& aStartTime,
task.Wait(); task.Wait();
} }
void
WebRenderAPI::ClearAllCaches()
{
wr_api_clear_all_caches(mDocHandle);
}
void void
WebRenderAPI::Pause() WebRenderAPI::Pause()
{ {

View file

@ -198,6 +198,8 @@ public:
void Readback(const TimeStamp& aStartTime, gfx::IntSize aSize, uint8_t *aBuffer, uint32_t aBufferSize); void Readback(const TimeStamp& aStartTime, gfx::IntSize aSize, uint8_t *aBuffer, uint32_t aBufferSize);
void ClearAllCaches();
void Pause(); void Pause();
bool Resume(); bool Resume();

View file

@ -1029,6 +1029,12 @@ pub unsafe extern "C" fn wr_api_shut_down(dh: &mut DocumentHandle) {
dh.api.shut_down(); dh.api.shut_down();
} }
/// cbindgen:postfix=WR_DESTRUCTOR_SAFE_FUNC
#[no_mangle]
pub unsafe extern "C" fn wr_api_clear_all_caches(dh: &mut DocumentHandle) {
dh.api.send_debug_cmd(DebugCommand::ClearCaches(ClearCache::all()));
}
fn make_transaction(do_async: bool) -> Transaction { fn make_transaction(do_async: bool) -> Transaction {
let mut transaction = Transaction::new(); let mut transaction = Transaction::new();
// Ensure that we either use async scene building or not based on the // Ensure that we either use async scene building or not based on the

View file

@ -1050,6 +1050,10 @@ void wr_api_capture(DocumentHandle *aDh,
uint32_t aBitsRaw) uint32_t aBitsRaw)
WR_FUNC; WR_FUNC;
WR_INLINE
void wr_api_clear_all_caches(DocumentHandle *aDh)
WR_DESTRUCTOR_SAFE_FUNC;
WR_INLINE WR_INLINE
void wr_api_clone(DocumentHandle *aDh, void wr_api_clone(DocumentHandle *aDh,
DocumentHandle **aOutHandle) DocumentHandle **aOutHandle)

View file

@ -339,6 +339,15 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
sandboxedLoadingPrincipalInfo = sandboxedLoadingPrincipalInfoTemp; sandboxedLoadingPrincipalInfo = sandboxedLoadingPrincipalInfoTemp;
} }
OptionalPrincipalInfo topLevelPrincipalInfo = mozilla::void_t();
if (aLoadInfo->TopLevelPrincipal()) {
PrincipalInfo topLevelPrincipalInfoTemp;
rv = PrincipalToPrincipalInfo(aLoadInfo->TopLevelPrincipal(),
&topLevelPrincipalInfoTemp);
NS_ENSURE_SUCCESS(rv, rv);
topLevelPrincipalInfo = topLevelPrincipalInfoTemp;
}
OptionalPrincipalInfo topLevelStorageAreaPrincipalInfo = mozilla::void_t(); OptionalPrincipalInfo topLevelStorageAreaPrincipalInfo = mozilla::void_t();
if (aLoadInfo->TopLevelStorageAreaPrincipal()) { if (aLoadInfo->TopLevelStorageAreaPrincipal()) {
PrincipalInfo topLevelStorageAreaPrincipalInfoTemp; PrincipalInfo topLevelStorageAreaPrincipalInfoTemp;
@ -408,6 +417,7 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
triggeringPrincipalInfo, triggeringPrincipalInfo,
principalToInheritInfo, principalToInheritInfo,
sandboxedLoadingPrincipalInfo, sandboxedLoadingPrincipalInfo,
topLevelPrincipalInfo,
topLevelStorageAreaPrincipalInfo, topLevelStorageAreaPrincipalInfo,
optionalResultPrincipalURI, optionalResultPrincipalURI,
aLoadInfo->GetSecurityFlags(), aLoadInfo->GetSecurityFlags(),
@ -488,6 +498,13 @@ LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs,
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
nsCOMPtr<nsIPrincipal> topLevelPrincipal;
if (loadInfoArgs.topLevelPrincipalInfo().type() != OptionalPrincipalInfo::Tvoid_t) {
topLevelPrincipal =
PrincipalInfoToPrincipal(loadInfoArgs.topLevelPrincipalInfo(), &rv);
NS_ENSURE_SUCCESS(rv, rv);
}
nsCOMPtr<nsIPrincipal> topLevelStorageAreaPrincipal; nsCOMPtr<nsIPrincipal> topLevelStorageAreaPrincipal;
if (loadInfoArgs.topLevelStorageAreaPrincipalInfo().type() != OptionalPrincipalInfo::Tvoid_t) { if (loadInfoArgs.topLevelStorageAreaPrincipalInfo().type() != OptionalPrincipalInfo::Tvoid_t) {
topLevelStorageAreaPrincipal = topLevelStorageAreaPrincipal =
@ -561,6 +578,7 @@ LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs,
triggeringPrincipal, triggeringPrincipal,
principalToInherit, principalToInherit,
sandboxedLoadingPrincipal, sandboxedLoadingPrincipal,
topLevelPrincipal,
topLevelStorageAreaPrincipal, topLevelStorageAreaPrincipal,
resultPrincipalURI, resultPrincipalURI,
clientInfo, clientInfo,

View file

@ -8,6 +8,8 @@ import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.AssertCalled
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.WithDisplay import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.WithDisplay
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.WithDevToolsAPI import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.WithDevToolsAPI
import android.graphics.Rect
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
@ -30,12 +32,16 @@ import org.junit.Before
import org.junit.After import org.junit.After
import org.junit.runner.RunWith import org.junit.runner.RunWith
const val DISPLAY_WIDTH = 480
const val DISPLAY_HEIGHT = 640
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
@MediumTest @MediumTest
@WithDisplay(width = 480, height = 640) @WithDisplay(width = DISPLAY_WIDTH, height = DISPLAY_HEIGHT)
@WithDevToolsAPI @WithDevToolsAPI
class AccessibilityTest : BaseSessionTest() { class AccessibilityTest : BaseSessionTest() {
lateinit var view: View lateinit var view: View
val screenRect = Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT)
val provider: AccessibilityNodeProvider get() = view.accessibilityNodeProvider val provider: AccessibilityNodeProvider get() = view.accessibilityNodeProvider
// Given a child ID, return the virtual descendent ID. // Given a child ID, return the virtual descendent ID.
@ -64,9 +70,12 @@ class AccessibilityTest : BaseSessionTest() {
fun onAccessibilityFocused(event: AccessibilityEvent) { } fun onAccessibilityFocused(event: AccessibilityEvent) { }
fun onClicked(event: AccessibilityEvent) { } fun onClicked(event: AccessibilityEvent) { }
fun onFocused(event: AccessibilityEvent) { } fun onFocused(event: AccessibilityEvent) { }
fun onSelected(event: AccessibilityEvent) { }
fun onScrolled(event: AccessibilityEvent) { }
fun onTextSelectionChanged(event: AccessibilityEvent) { } fun onTextSelectionChanged(event: AccessibilityEvent) { }
fun onTextChanged(event: AccessibilityEvent) { } fun onTextChanged(event: AccessibilityEvent) { }
fun onTextTraversal(event: AccessibilityEvent) { } fun onTextTraversal(event: AccessibilityEvent) { }
fun onWinStateChanged(event: AccessibilityEvent) { }
} }
@Before fun setup() { @Before fun setup() {
@ -90,9 +99,12 @@ class AccessibilityTest : BaseSessionTest() {
AccessibilityEvent.TYPE_VIEW_FOCUSED -> newDelegate.onFocused(event) AccessibilityEvent.TYPE_VIEW_FOCUSED -> newDelegate.onFocused(event)
AccessibilityEvent.TYPE_VIEW_CLICKED -> newDelegate.onClicked(event) AccessibilityEvent.TYPE_VIEW_CLICKED -> newDelegate.onClicked(event)
AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED -> newDelegate.onAccessibilityFocused(event) AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED -> newDelegate.onAccessibilityFocused(event)
AccessibilityEvent.TYPE_VIEW_SELECTED -> newDelegate.onSelected(event)
AccessibilityEvent.TYPE_VIEW_SCROLLED -> newDelegate.onScrolled(event)
AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED -> newDelegate.onTextSelectionChanged(event) AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED -> newDelegate.onTextSelectionChanged(event)
AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED -> newDelegate.onTextChanged(event) AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED -> newDelegate.onTextChanged(event)
AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY -> newDelegate.onTextTraversal(event) AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY -> newDelegate.onTextTraversal(event)
AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED -> newDelegate.onWinStateChanged(event)
else -> {} else -> {}
} }
return false return false
@ -204,21 +216,25 @@ class AccessibilityTest : BaseSessionTest() {
}) })
} }
private fun waitUntilClick(checked: Boolean? = null, selected: Boolean? = null) { private fun waitUntilClick(checked: Boolean) {
sessionRule.waitUntilCalled(object : EventDelegate { sessionRule.waitUntilCalled(object : EventDelegate {
@AssertCalled(count = 1) @AssertCalled(count = 1)
override fun onClicked(event: AccessibilityEvent) { override fun onClicked(event: AccessibilityEvent) {
var nodeId = getSourceId(event) var nodeId = getSourceId(event)
var node = provider.createAccessibilityNodeInfo(nodeId) var node = provider.createAccessibilityNodeInfo(nodeId)
assertThat("Event's checked state matches", event.isChecked, equalTo(checked))
assertThat("Checkbox node has correct checked state", node.isChecked, equalTo(checked))
}
})
}
if (checked != null) { private fun waitUntilSelect(selected: Boolean) {
assertThat("Event's checked state matches", event.isChecked, equalTo(checked)) sessionRule.waitUntilCalled(object : EventDelegate {
assertThat("Checkbox node has correct checked state", node.isChecked, equalTo(checked)) @AssertCalled(count = 1)
} override fun onSelected(event: AccessibilityEvent) {
var nodeId = getSourceId(event)
if (selected != null) { var node = provider.createAccessibilityNodeInfo(nodeId)
assertThat("Selectable node has correct selected state", node.isSelected, equalTo(selected)) assertThat("Selectable node has correct selected state", node.isSelected, equalTo(selected))
}
} }
}) })
} }
@ -407,10 +423,10 @@ class AccessibilityTest : BaseSessionTest() {
}) })
provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_CLICK, null) provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_CLICK, null)
waitUntilClick(checked = true) waitUntilClick(true)
provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_CLICK, null) provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_CLICK, null)
waitUntilClick(checked = false) waitUntilClick(false)
} }
@Test fun testSelectable() { @Test fun testSelectable() {
@ -435,9 +451,115 @@ class AccessibilityTest : BaseSessionTest() {
}) })
provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_CLICK, null) provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_CLICK, null)
waitUntilClick(selected = true) waitUntilSelect(true)
provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_CLICK, null) provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_CLICK, null)
waitUntilClick(selected = false) waitUntilSelect(false)
provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_SELECT, null)
waitUntilSelect(true)
provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_SELECT, null)
waitUntilSelect(false)
}
private fun screenContainsNode(nodeId: Int): Boolean {
var node = provider.createAccessibilityNodeInfo(nodeId)
var nodeBounds = Rect()
node.getBoundsInScreen(nodeBounds)
return screenRect.contains(nodeBounds)
}
@Test fun testScroll() {
var nodeId = View.NO_ID
sessionRule.session.loadString(
"""<body style="margin: 0;">
<div style="height: 100vh;"></div>
<button>Hello</button>
<p style="margin: 0;">Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
</body>""",
"text/html")
sessionRule.waitForPageStop()
sessionRule.waitUntilCalled(object : EventDelegate {
@AssertCalled(count = 1)
override fun onFocused(event: AccessibilityEvent) {
nodeId = getSourceId(event)
var node = provider.createAccessibilityNodeInfo(nodeId)
var nodeBounds = Rect()
node.getBoundsInParent(nodeBounds)
assertThat("Default root node bounds are correct", nodeBounds, equalTo(screenRect))
}
})
provider.performAction(View.NO_ID, AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null)
sessionRule.waitUntilCalled(object : EventDelegate {
@AssertCalled(count = 1, order = [1])
override fun onAccessibilityFocused(event: AccessibilityEvent) {
nodeId = getSourceId(event)
assertThat("Focused node is onscreen", screenContainsNode(nodeId), equalTo(true))
}
@AssertCalled(count = 1, order = [2])
override fun onScrolled(event: AccessibilityEvent) {
assertThat("View is scrolled for focused node to be onscreen", event.scrollY, greaterThan(0))
assertThat("View is not scrolled to the end", event.scrollY, lessThan(event.maxScrollY))
}
@AssertCalled(count = 1, order = [3])
override fun onWinStateChanged(event: AccessibilityEvent) {
nodeId = getSourceId(event)
assertThat("Focused node is onscreen", screenContainsNode(nodeId), equalTo(true))
}
})
provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_SCROLL_FORWARD, null)
sessionRule.waitUntilCalled(object : EventDelegate {
@AssertCalled(count = 1, order = [1])
override fun onScrolled(event: AccessibilityEvent) {
assertThat("View is scrolled to the end", event.scrollY, equalTo(event.maxScrollY))
}
@AssertCalled(count = 1, order = [2])
override fun onWinStateChanged(event: AccessibilityEvent) {
nodeId = getSourceId(event)
assertThat("Focused node is still onscreen", screenContainsNode(nodeId), equalTo(true))
}
})
provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD, null)
sessionRule.waitUntilCalled(object : EventDelegate {
@AssertCalled(count = 1, order = [1])
override fun onScrolled(event: AccessibilityEvent) {
assertThat("View is scrolled to the beginning", event.scrollY, equalTo(0))
}
@AssertCalled(count = 1, order = [2])
override fun onWinStateChanged(event: AccessibilityEvent) {
nodeId = getSourceId(event)
assertThat("Focused node is offscreen", screenContainsNode(nodeId), equalTo(false))
}
})
provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT, null)
sessionRule.waitUntilCalled(object : EventDelegate {
@AssertCalled(count = 1, order = [1])
override fun onAccessibilityFocused(event: AccessibilityEvent) {
nodeId = getSourceId(event)
assertThat("Focused node is onscreen", screenContainsNode(nodeId), equalTo(true))
}
@AssertCalled(count = 1, order = [2])
override fun onScrolled(event: AccessibilityEvent) {
assertThat("View is scrolled to the end", event.scrollY, equalTo(event.maxScrollY))
}
@AssertCalled(count = 1, order = [3])
override fun onWinStateChanged(event: AccessibilityEvent) {
nodeId = getSourceId(event)
assertThat("Focused node is onscreen", screenContainsNode(nodeId), equalTo(true))
}
})
} }
} }

View file

@ -189,6 +189,9 @@ public class SessionAccessibility {
case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD:
mSession.getEventDispatcher().dispatch("GeckoView:AccessibilityScrollBackward", null); mSession.getEventDispatcher().dispatch("GeckoView:AccessibilityScrollBackward", null);
return true; return true;
case AccessibilityNodeInfo.ACTION_SELECT:
mSession.getEventDispatcher().dispatch("GeckoView:AccessibilitySelect", null);
return true;
case AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT: case AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT:
if (mLastItem) { if (mLastItem) {
return false; return false;
@ -483,8 +486,9 @@ public class SessionAccessibility {
// Bounds for the virtual content can be updated from any event. // Bounds for the virtual content can be updated from any event.
updateBounds(mVirtualContentNode, message); updateBounds(mVirtualContentNode, message);
// State for the virtual content can be updated when view is clicked. // State for the virtual content can be updated when view is clicked/selected.
if (eventType == AccessibilityEvent.TYPE_VIEW_CLICKED) { if (eventType == AccessibilityEvent.TYPE_VIEW_CLICKED ||
eventType == AccessibilityEvent.TYPE_VIEW_SELECTED) {
updateState(mVirtualContentNode, message); updateState(mVirtualContentNode, message);
} }
} }

View file

@ -867,6 +867,18 @@ VARCACHE_PREF(
bool, false bool, false
) )
#if defined(MOZ_WEBM_ENCODER)
# define PREF_VALUE true
#else
# define PREF_VALUE false
#endif
VARCACHE_PREF(
"media.encoder.webm.enabled",
MediaEncoderWebMEnabled,
RelaxedAtomicBool, true
)
#undef PREF_VALUE
#if defined(RELEASE_OR_BETA) #if defined(RELEASE_OR_BETA)
# define PREF_VALUE 3 # define PREF_VALUE 3
#else #else

View file

@ -155,6 +155,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
nsGlobalWindowInner* innerWindow = nsGlobalWindowInner* innerWindow =
nsGlobalWindowInner::Cast(contextOuter->GetCurrentInnerWindow()); nsGlobalWindowInner::Cast(contextOuter->GetCurrentInnerWindow());
if (innerWindow) { if (innerWindow) {
mTopLevelPrincipal = innerWindow->GetTopLevelPrincipal();
mTopLevelStorageAreaPrincipal = mTopLevelStorageAreaPrincipal =
innerWindow->GetTopLevelStorageAreaPrincipal(); innerWindow->GetTopLevelStorageAreaPrincipal();
} }
@ -346,6 +347,7 @@ LoadInfo::LoadInfo(nsPIDOMWindowOuter* aOuterWindow,
nsGlobalWindowInner* innerWindow = nsGlobalWindowInner* innerWindow =
nsGlobalWindowInner::Cast(aOuterWindow->GetCurrentInnerWindow()); nsGlobalWindowInner::Cast(aOuterWindow->GetCurrentInnerWindow());
if (innerWindow) { if (innerWindow) {
mTopLevelPrincipal = innerWindow->GetTopLevelPrincipal();
mTopLevelStorageAreaPrincipal = mTopLevelStorageAreaPrincipal =
innerWindow->GetTopLevelStorageAreaPrincipal(); innerWindow->GetTopLevelStorageAreaPrincipal();
} }
@ -371,6 +373,7 @@ LoadInfo::LoadInfo(const LoadInfo& rhs)
, mTriggeringPrincipal(rhs.mTriggeringPrincipal) , mTriggeringPrincipal(rhs.mTriggeringPrincipal)
, mPrincipalToInherit(rhs.mPrincipalToInherit) , mPrincipalToInherit(rhs.mPrincipalToInherit)
, mSandboxedLoadingPrincipal(rhs.mSandboxedLoadingPrincipal) , mSandboxedLoadingPrincipal(rhs.mSandboxedLoadingPrincipal)
, mTopLevelPrincipal(rhs.mTopLevelPrincipal)
, mTopLevelStorageAreaPrincipal(rhs.mTopLevelStorageAreaPrincipal) , mTopLevelStorageAreaPrincipal(rhs.mTopLevelStorageAreaPrincipal)
, mResultPrincipalURI(rhs.mResultPrincipalURI) , mResultPrincipalURI(rhs.mResultPrincipalURI)
, mClientInfo(rhs.mClientInfo) , mClientInfo(rhs.mClientInfo)
@ -423,6 +426,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
nsIPrincipal* aTriggeringPrincipal, nsIPrincipal* aTriggeringPrincipal,
nsIPrincipal* aPrincipalToInherit, nsIPrincipal* aPrincipalToInherit,
nsIPrincipal* aSandboxedLoadingPrincipal, nsIPrincipal* aSandboxedLoadingPrincipal,
nsIPrincipal* aTopLevelPrincipal,
nsIPrincipal* aTopLevelStorageAreaPrincipal, nsIPrincipal* aTopLevelStorageAreaPrincipal,
nsIURI* aResultPrincipalURI, nsIURI* aResultPrincipalURI,
const Maybe<ClientInfo>& aClientInfo, const Maybe<ClientInfo>& aClientInfo,
@ -464,6 +468,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
: mLoadingPrincipal(aLoadingPrincipal) : mLoadingPrincipal(aLoadingPrincipal)
, mTriggeringPrincipal(aTriggeringPrincipal) , mTriggeringPrincipal(aTriggeringPrincipal)
, mPrincipalToInherit(aPrincipalToInherit) , mPrincipalToInherit(aPrincipalToInherit)
, mTopLevelPrincipal(aTopLevelPrincipal)
, mTopLevelStorageAreaPrincipal(aTopLevelStorageAreaPrincipal) , mTopLevelStorageAreaPrincipal(aTopLevelStorageAreaPrincipal)
, mResultPrincipalURI(aResultPrincipalURI) , mResultPrincipalURI(aResultPrincipalURI)
, mClientInfo(aClientInfo) , mClientInfo(aClientInfo)
@ -647,6 +652,19 @@ LoadInfo::GetSandboxedLoadingPrincipal(nsIPrincipal** aPrincipal)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
LoadInfo::GetTopLevelPrincipal(nsIPrincipal** aTopLevelPrincipal)
{
NS_IF_ADDREF(*aTopLevelPrincipal = mTopLevelPrincipal);
return NS_OK;
}
nsIPrincipal*
LoadInfo::TopLevelPrincipal()
{
return mTopLevelPrincipal;
}
NS_IMETHODIMP NS_IMETHODIMP
LoadInfo::GetTopLevelStorageAreaPrincipal(nsIPrincipal** aTopLevelStorageAreaPrincipal) LoadInfo::GetTopLevelStorageAreaPrincipal(nsIPrincipal** aTopLevelStorageAreaPrincipal)
{ {

View file

@ -97,6 +97,7 @@ private:
nsIPrincipal* aTriggeringPrincipal, nsIPrincipal* aTriggeringPrincipal,
nsIPrincipal* aPrincipalToInherit, nsIPrincipal* aPrincipalToInherit,
nsIPrincipal* aSandboxedLoadingPrincipal, nsIPrincipal* aSandboxedLoadingPrincipal,
nsIPrincipal* aTopLevelPrincipal,
nsIPrincipal* aTopLevelStorageAreaPrincipal, nsIPrincipal* aTopLevelStorageAreaPrincipal,
nsIURI* aResultPrincipalURI, nsIURI* aResultPrincipalURI,
const Maybe<mozilla::dom::ClientInfo>& aClientInfo, const Maybe<mozilla::dom::ClientInfo>& aClientInfo,
@ -161,6 +162,7 @@ private:
nsCOMPtr<nsIPrincipal> mTriggeringPrincipal; nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
nsCOMPtr<nsIPrincipal> mPrincipalToInherit; nsCOMPtr<nsIPrincipal> mPrincipalToInherit;
nsCOMPtr<nsIPrincipal> mSandboxedLoadingPrincipal; nsCOMPtr<nsIPrincipal> mSandboxedLoadingPrincipal;
nsCOMPtr<nsIPrincipal> mTopLevelPrincipal;
nsCOMPtr<nsIPrincipal> mTopLevelStorageAreaPrincipal; nsCOMPtr<nsIPrincipal> mTopLevelStorageAreaPrincipal;
nsCOMPtr<nsIURI> mResultPrincipalURI; nsCOMPtr<nsIURI> mResultPrincipalURI;

View file

@ -883,6 +883,18 @@ interface nsILoadInfo : nsISupports
*/ */
[noscript] readonly attribute nsIPrincipal sandboxedLoadingPrincipal; [noscript] readonly attribute nsIPrincipal sandboxedLoadingPrincipal;
/**
* Return the top-level principal, which is the principal of the top-level
* window.
*/
[noscript] readonly attribute nsIPrincipal topLevelPrincipal;
/**
* A C++-friendly version of topLevelPrincipal.
*/
[noscript, notxpcom, nostdcall, binaryname(TopLevelPrincipal)]
nsIPrincipal binaryTopLevelPrincipal();
/** /**
* Return the top-level storage area principal, which is the principal of * Return the top-level storage area principal, which is the principal of
* the top-level window if it's not a 3rd party context, non tracking * the top-level window if it's not a 3rd party context, non tracking

View file

@ -42,6 +42,7 @@ struct LoadInfoArgs
PrincipalInfo triggeringPrincipalInfo; PrincipalInfo triggeringPrincipalInfo;
OptionalPrincipalInfo principalToInheritInfo; OptionalPrincipalInfo principalToInheritInfo;
OptionalPrincipalInfo sandboxedLoadingPrincipalInfo; OptionalPrincipalInfo sandboxedLoadingPrincipalInfo;
OptionalPrincipalInfo topLevelPrincipalInfo;
OptionalPrincipalInfo topLevelStorageAreaPrincipalInfo; OptionalPrincipalInfo topLevelStorageAreaPrincipalInfo;
OptionalURIParams resultPrincipalURI; OptionalURIParams resultPrincipalURI;
uint32_t securityFlags; uint32_t securityFlags;

Some files were not shown because too many files have changed in this diff Show more