Update On Fri Jan 24 19:53:20 CET 2025

This commit is contained in:
github-action[bot] 2025-01-24 19:53:21 +01:00
parent 1ed0aa2bc4
commit 673f42f59c
509 changed files with 13383 additions and 7473 deletions

View file

@ -275,16 +275,16 @@ const nsDependentSubstring AssociatedElementsIterator::NextID() {
return Substring(mIDs, idStartIdx, mCurrIdx++ - idStartIdx); return Substring(mIDs, idStartIdx, mCurrIdx++ - idStartIdx);
} }
nsIContent* AssociatedElementsIterator::NextElem() { dom::Element* AssociatedElementsIterator::NextElem() {
while (true) { while (true) {
const nsDependentSubstring id = NextID(); const nsDependentSubstring id = NextID();
if (id.IsEmpty()) break; if (id.IsEmpty()) break;
nsIContent* refContent = GetElem(id); dom::Element* refContent = GetElem(id);
if (refContent) return refContent; if (refContent) return refContent;
} }
while (nsIContent* element = mElements.SafeElementAt(mElemIdx++)) { while (dom::Element* element = mElements.SafeElementAt(mElemIdx++)) {
if (nsCoreUtils::IsDescendantOfAnyShadowIncludingAncestor(element, if (nsCoreUtils::IsDescendantOfAnyShadowIncludingAncestor(element,
mContent)) { mContent)) {
return element; return element;
@ -317,7 +317,7 @@ dom::Element* AssociatedElementsIterator::GetElem(
} }
LocalAccessible* AssociatedElementsIterator::Next() { LocalAccessible* AssociatedElementsIterator::Next() {
nsIContent* nextEl = nullptr; dom::Element* nextEl = nullptr;
while ((nextEl = NextElem())) { while ((nextEl = NextElem())) {
LocalAccessible* acc = mDoc->GetAccessible(nextEl); LocalAccessible* acc = mDoc->GetAccessible(nextEl);
if (acc) { if (acc) {

View file

@ -225,7 +225,7 @@ class AssociatedElementsIterator : public AccIterable {
/** /**
* Return next element. * Return next element.
*/ */
nsIContent* NextElem(); dom::Element* NextElem();
/** /**
* Return the element with the given ID. * Return the element with the given ID.

View file

@ -595,23 +595,6 @@ void NotificationController::ProcessMutationEvents() {
} }
} }
// Fire menupopup end event before a hide event if a menu goes away.
// XXX: We don't look into children of hidden subtree to find hiding
// menupopup (as we did prior bug 570275) because we don't do that when
// menu is showing (and that's impossible until bug 606924 is fixed).
// Nevertheless we should do this at least because layout coalesces
// the changes before our processing and we may miss some menupopup
// events. Now we just want to be consistent in content insertion/removal
// handling.
if (event->mAccessible->ARIARole() == roles::MENUPOPUP) {
nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_END,
event->mAccessible);
if (!mDocument) {
return;
}
}
AccHideEvent* hideEvent = downcast_accEvent(event); AccHideEvent* hideEvent = downcast_accEvent(event);
if (hideEvent->NeedsShutdown()) { if (hideEvent->NeedsShutdown()) {
mDocument->ShutdownChildrenInSubtree(event->mAccessible); mDocument->ShutdownChildrenInSubtree(event->mAccessible);

View file

@ -121,16 +121,6 @@ inline void DocAccessible::CreateSubtree(LocalAccessible* aChild) {
} }
#endif #endif
// Fire events for ARIA elements.
if (aChild->HasARIARole()) {
roles::Role role = aChild->ARIARole();
if (role == roles::MENUPOPUP) {
FireDelayedEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START, aChild);
} else if (role == roles::ALERT) {
FireDelayedEvent(nsIAccessibleEvent::EVENT_ALERT, aChild);
}
}
// XXX: do we really want to send focus to focused DOM node not taking into // XXX: do we really want to send focus to focused DOM node not taking into
// account active item? // account active item?
if (focusedAcc) { if (focusedAcc) {

View file

@ -999,22 +999,38 @@ void DocAccessible::ContentAppended(nsIContent* aFirstNewContent) {
void DocAccessible::ElementStateChanged(dom::Document* aDocument, void DocAccessible::ElementStateChanged(dom::Document* aDocument,
dom::Element* aElement, dom::Element* aElement,
dom::ElementState aStateMask) { dom::ElementState aStateMask) {
if (aStateMask.HasState(dom::ElementState::READWRITE) && LocalAccessible* accessible =
aElement == mDocumentNode->GetRootElement()) { aElement == mContent ? this : GetAccessible(aElement);
// This handles changes to designMode. contentEditable is handled by
// LocalAccessible::AttributeChangesState and if (!accessible) {
// LocalAccessible::DOMAttributeChanged. return;
}
if (aStateMask.HasState(dom::ElementState::READWRITE)) {
const bool isEditable = const bool isEditable =
aElement->State().HasState(dom::ElementState::READWRITE); aElement->State().HasState(dom::ElementState::READWRITE);
RefPtr<AccEvent> event = RefPtr<AccEvent> event =
new AccStateChangeEvent(this, states::EDITABLE, isEditable); new AccStateChangeEvent(accessible, states::EDITABLE, isEditable);
FireDelayedEvent(event); FireDelayedEvent(event);
event = new AccStateChangeEvent(this, states::READONLY, !isEditable); if (accessible == this || aElement->IsHTMLElement(nsGkAtoms::article)) {
FireDelayedEvent(event); // We want <article> to behave like a document in terms of readonly state.
} event =
new AccStateChangeEvent(accessible, states::READONLY, !isEditable);
FireDelayedEvent(event);
}
LocalAccessible* accessible = GetAccessible(aElement); if (aElement->HasAttr(nsGkAtoms::aria_owns)) {
if (!accessible) return; // If this has aria-owns, update children that are relocated into here.
// If we are becoming editable, put them back into their original
// containers, if we are becoming readonly, acquire them.
mNotificationController->ScheduleRelocation(accessible);
}
// If this is a node inside of a newly editable subtree, it needs to be
// un-aria-owned. And inversely, if the node becomes uneditable, allow the
// node to be aria-owned.
RelocateARIAOwnedIfNeeded(aElement);
}
if (aStateMask.HasState(dom::ElementState::CHECKED)) { if (aStateMask.HasState(dom::ElementState::CHECKED)) {
LocalAccessible* widget = accessible->ContainerWidget(); LocalAccessible* widget = accessible->ContainerWidget();
@ -2456,9 +2472,24 @@ void DocAccessible::DoARIAOwnsRelocation(LocalAccessible* aOwner) {
nsTArray<RefPtr<LocalAccessible>>* owned = nsTArray<RefPtr<LocalAccessible>>* owned =
mARIAOwnsHash.GetOrInsertNew(aOwner); mARIAOwnsHash.GetOrInsertNew(aOwner);
if (aOwner->Elm()->State().HasState(dom::ElementState::READWRITE)) {
// The container is editable.
PutChildrenBack(owned, 0);
return;
}
AssociatedElementsIterator iter(this, aOwner->Elm(), nsGkAtoms::aria_owns); AssociatedElementsIterator iter(this, aOwner->Elm(), nsGkAtoms::aria_owns);
uint32_t idx = 0; uint32_t idx = 0;
while (nsIContent* childEl = iter.NextElem()) { while (dom::Element* childEl = iter.NextElem()) {
if (childEl->State().HasState(dom::ElementState::READWRITE)) {
nsINode* parentEl = childEl->GetFlattenedTreeParentNode();
if (parentEl->IsElement() && parentEl->AsElement()->State().HasState(
dom::ElementState::READWRITE)) {
// The child is inside of an editable subtree, don't relocate it.
continue;
}
}
LocalAccessible* child = GetAccessible(childEl); LocalAccessible* child = GetAccessible(childEl);
auto insertIdx = aOwner->ChildCount() - owned->Length() + idx; auto insertIdx = aOwner->ChildCount() - owned->Length() + idx;
@ -2808,17 +2839,26 @@ void DocAccessible::CacheChildrenInSubtree(LocalAccessible* aRoot,
return; return;
} }
// XXX: we should delay document load complete event if the ARIA document
// has aria-busy.
roles::Role role = aRoot->ARIARole(); roles::Role role = aRoot->ARIARole();
if (!aRoot->IsDoc() && if (!aRoot->IsDoc()) {
(role == roles::DIALOG || role == roles::NON_NATIVE_DOCUMENT)) { if (role == roles::DIALOG || role == roles::NON_NATIVE_DOCUMENT) {
FireDelayedEvent(nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE, aRoot); // XXX: we should delay document load complete event if the ARIA document
// has aria-busy.
FireDelayedEvent(nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE, aRoot);
} else if (role == roles::MENUPOPUP && HasLoadState(eCompletelyLoaded)) {
FireDelayedEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START, aRoot);
} else if (role == roles::ALERT && HasLoadState(eCompletelyLoaded)) {
FireDelayedEvent(nsIAccessibleEvent::EVENT_ALERT, aRoot);
}
} }
} }
void DocAccessible::UncacheChildrenInSubtree(LocalAccessible* aRoot) { void DocAccessible::UncacheChildrenInSubtree(LocalAccessible* aRoot) {
MaybeFireEventsForChangedPopover(aRoot); MaybeFireEventsForChangedPopover(aRoot);
if (aRoot->ARIARole() == roles::MENUPOPUP) {
nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_END, aRoot);
}
aRoot->mStateFlags |= eIsNotInDocument; aRoot->mStateFlags |= eIsNotInDocument;
RemoveDependentIDsFor(aRoot); RemoveDependentIDsFor(aRoot);
RemoveDependentElementsFor(aRoot); RemoveDependentElementsFor(aRoot);

View file

@ -1298,6 +1298,7 @@ bool LocalAccessible::AttributeChangesState(nsAtom* aAttribute) {
aAttribute == nsGkAtoms::aria_busy || aAttribute == nsGkAtoms::aria_busy ||
aAttribute == nsGkAtoms::aria_multiline || aAttribute == nsGkAtoms::aria_multiline ||
aAttribute == nsGkAtoms::aria_multiselectable || aAttribute == nsGkAtoms::aria_multiselectable ||
// We track this for focusable state update
aAttribute == nsGkAtoms::contenteditable || aAttribute == nsGkAtoms::contenteditable ||
aAttribute == nsGkAtoms::popovertarget; aAttribute == nsGkAtoms::popovertarget;
} }

View file

@ -312,10 +312,12 @@ addAccessibleTask(
* Test caching of the editable state. * Test caching of the editable state.
*/ */
addAccessibleTask( addAccessibleTask(
`<div id="div" contenteditable></div>`, `<div id="div" contenteditable><p id="p">hello</p></div>`,
async function (browser, docAcc) { async function (browser, docAcc) {
const div = findAccessibleChildByID(docAcc, "div"); const div = findAccessibleChildByID(docAcc, "div");
const p = findAccessibleChildByID(docAcc, "p");
testStates(div, 0, EXT_STATE_EDITABLE, 0, 0); testStates(div, 0, EXT_STATE_EDITABLE, 0, 0);
testStates(p, 0, EXT_STATE_EDITABLE, 0, 0);
// Ensure that a contentEditable descendant doesn't cause editable to be // Ensure that a contentEditable descendant doesn't cause editable to be
// exposed on the document. // exposed on the document.
testStates(docAcc, STATE_READONLY, 0, 0, EXT_STATE_EDITABLE); testStates(docAcc, STATE_READONLY, 0, 0, EXT_STATE_EDITABLE);
@ -349,6 +351,7 @@ addAccessibleTask(
}); });
await stateChanged; await stateChanged;
testStates(div, 0, 0, 0, EXT_STATE_EDITABLE); testStates(div, 0, 0, 0, EXT_STATE_EDITABLE);
testStates(p, 0, 0, 0, EXT_STATE_EDITABLE);
info("Setting contentEditable on div"); info("Setting contentEditable on div");
stateChanged = waitForStateChange(div, EXT_STATE_EDITABLE, true, true); stateChanged = waitForStateChange(div, EXT_STATE_EDITABLE, true, true);

View file

@ -6,6 +6,8 @@
/* import-globals-from ../../mochitest/role.js */ /* import-globals-from ../../mochitest/role.js */
loadScripts({ name: "role.js", dir: MOCHITESTS_DIR }); loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
/* import-globals-from ../../mochitest/states.js */
loadScripts({ name: "states.js", dir: MOCHITESTS_DIR });
requestLongerTimeout(2); requestLongerTimeout(2);
@ -606,3 +608,95 @@ addAccessibleTask(`<div id='a'></div>`, async function (browser, accDoc) {
}); });
is(getAccessibleDOMNodeID(a.firstChild), "b", "'a' owns relocated child"); is(getAccessibleDOMNodeID(a.firstChild), "b", "'a' owns relocated child");
}); });
/*
* Test to assure that aria-owned elements are not relocated into an editable subtree.
*/
addAccessibleTask(
`
<button id="btn">World</button>
<div contentEditable="true" id="textbox" role="textbox">
<p id="p" aria-owns="btn">Hello</p>
</div>
`,
async function (browser, accDoc) {
const p = findAccessibleChildByID(accDoc, "p");
const textbox = findAccessibleChildByID(accDoc, "textbox");
testStates(textbox, 0, EXT_STATE_EDITABLE, 0, 0);
isnot(getAccessibleDOMNodeID(p.lastChild), "btn", "'p' owns relocated btn");
is(textbox.value, "Hello");
let expectedEvents = Promise.all([
waitForStateChange(textbox, EXT_STATE_EDITABLE, false, true),
waitForEvent(EVENT_INNER_REORDER, p),
]);
await invokeContentTask(browser, [], () => {
content.document.getElementById("textbox").contentEditable = false;
});
await expectedEvents;
is(getAccessibleDOMNodeID(p.lastChild), "btn", "'p' owns relocated btn");
is(textbox.value, "Hello World");
expectedEvents = Promise.all([
waitForStateChange(textbox, EXT_STATE_EDITABLE, true, true),
waitForEvent(EVENT_INNER_REORDER, p),
]);
await invokeContentTask(browser, [], () => {
content.document.getElementById("textbox").contentEditable = true;
});
await expectedEvents;
isnot(getAccessibleDOMNodeID(p.lastChild), "btn", "'p' owns relocated btn");
is(textbox.value, "Hello");
}
);
/*
* Test to ensure that aria-owned elements are not relocated out of editable subtree.
*/
addAccessibleTask(
`
<div contentEditable="true" id="textbox" role="textbox">
<button id="btn">World</button>
</div>
<p id="p" aria-owns="btn">Hello</p>
<p id="p2" aria-owns="textbox"></p>
`,
async function (browser, accDoc) {
const p = findAccessibleChildByID(accDoc, "p");
const textbox = findAccessibleChildByID(accDoc, "textbox");
testStates(textbox, 0, EXT_STATE_EDITABLE, 0, 0);
is(
getAccessibleDOMNodeID(textbox.parent),
"p2",
"editable root can be relocated"
);
isnot(
getAccessibleDOMNodeID(p.lastChild),
"btn",
"editable element cannot be relocated"
);
is(textbox.value, "World");
let expectedEvents = Promise.all([
waitForStateChange(textbox, EXT_STATE_EDITABLE, false, true),
waitForEvent(EVENT_REORDER, p),
]);
await invokeContentTask(browser, [], () => {
content.document.getElementById("textbox").contentEditable = false;
});
await expectedEvents;
is(
getAccessibleDOMNodeID(p.lastChild),
"btn",
"'p' owns readonly relocated btn"
);
is(textbox.value, "");
is(
getAccessibleDOMNodeID(textbox.parent),
"p2",
"textbox is still relocated"
);
}
);

View file

@ -12,6 +12,8 @@ support-files = [
["browser_focus_document.js"] ["browser_focus_document.js"]
["browser_menu_and_alerts.js"]
["browser_test_A11yUtils_announce.js"] ["browser_test_A11yUtils_announce.js"]
["browser_test_caret_move_granularity.js"] ["browser_test_caret_move_granularity.js"]

View file

@ -0,0 +1,150 @@
/* 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/. */
"use strict";
/**
* Accessible menu popup start/end
*/
addAccessibleTask(
`
<div id="container">
<ul id="menu" role="menu" style="display: none;">
<li role="menuitem">Hello</li>
</ul>
</div>
`,
async function (browser) {
let expectedEvents = waitForEvents(
[
[EVENT_SHOW],
[EVENT_REORDER, "container"],
[EVENT_MENUPOPUP_START, "menu"],
],
"Popup start sequence",
true
);
await invokeContentTask(browser, [], () => {
content.document.getElementById("menu").style.display = "block";
});
await expectedEvents;
expectedEvents = waitForEvents(
[
[EVENT_MENUPOPUP_END, "menu"],
[EVENT_HIDE],
[EVENT_REORDER, "container"],
],
"Popup end sequence",
true
);
await invokeContentTask(browser, [], () => {
content.document.getElementById("menu").style.display = "none";
});
await expectedEvents;
},
{ chrome: true, topLevel: true }
);
/**
* Accessible menu popup start/end in subtree
*/
addAccessibleTask(
`
<div id="container" style="display: none;">
<ul id="menu" role="menu">
<li role="menuitem">Hello</li>
</ul>
</div>
`,
async function (browser, accDoc) {
let expectedEvents = waitForEvents(
[[EVENT_SHOW], [EVENT_REORDER, accDoc], [EVENT_MENUPOPUP_START, "menu"]],
"Embedded popup start sequence",
true
);
await invokeContentTask(browser, [], () => {
content.document.getElementById("container").style.display = "block";
});
await expectedEvents;
expectedEvents = waitForEvents(
[[EVENT_MENUPOPUP_END, "menu"], [EVENT_HIDE], [EVENT_REORDER, accDoc]],
"Embedded popup end sequence",
true
);
await invokeContentTask(browser, [], () => {
content.document.getElementById("container").style.display = "none";
});
await expectedEvents;
},
{ chrome: true, topLevel: true }
);
/**
* Accessible alert event
*/
addAccessibleTask(
`
<div id="container">
<div role="alert" id="alert" style="display: none;">Alert!</div>
</div>
`,
async function (browser, accDoc) {
let expectedEvents = waitForEvents(
[[EVENT_SHOW], [EVENT_REORDER, "container"], [EVENT_ALERT, "alert"]],
"Alert events sequence",
true
);
await invokeContentTask(browser, [], () => {
content.document.getElementById("alert").style.display = "block";
});
await expectedEvents;
expectedEvents = waitForEvent(EVENT_REORDER, accDoc);
await invokeContentTask(browser, [], () => {
content.document.getElementById("container").style.display = "none";
});
await expectedEvents;
expectedEvents = waitForEvents(
[[EVENT_SHOW], [EVENT_REORDER, accDoc], [EVENT_ALERT, "alert"]],
"Embedded Alert events sequence",
true
);
await invokeContentTask(browser, [], () => {
content.document.getElementById("container").style.display = "block";
});
await expectedEvents;
},
{ chrome: true, topLevel: true }
);
/**
* No alert event at load.
*/
addAccessibleTask(
``,
async function (browser) {
let onLoadEvents = waitForEvents({
expected: [
[EVENT_FOCUS, "body2"],
[EVENT_DOCUMENT_LOAD_COMPLETE, "body2"],
stateChangeEventArgs("body2", STATE_BUSY, false, false),
],
unexpected: [[EVENT_ALERT]],
});
BrowserTestUtils.startLoadingURIString(
browser,
`data:text/html;charset=utf-8,
<html><body id="body2">
<div role="alert" id="alert">Alert!</div>
</body></html>`
);
await onLoadEvents;
},
{ chrome: true, topLevel: true }
);

View file

@ -4,7 +4,7 @@
"use strict"; "use strict";
async function testComboBox(browser, accDoc, suppressPopupInValueTodo = false) { async function testComboBox(browser, accDoc) {
const box = getNativeInterface(accDoc, "box"); const box = getNativeInterface(accDoc, "box");
is(box.getAttributeValue("AXRole"), "AXComboBox"); is(box.getAttributeValue("AXRole"), "AXComboBox");
is(box.getAttributeValue("AXValue"), "peach", "Initial value correct"); is(box.getAttributeValue("AXValue"), "peach", "Initial value correct");
@ -20,19 +20,9 @@ async function testComboBox(browser, accDoc, suppressPopupInValueTodo = false) {
}); });
await expandedChanged; await expandedChanged;
if (suppressPopupInValueTodo) {
todo( ok(!didBoxValueChange, "Value of combobox did not change when it was opened");
!didBoxValueChange, is(box.getAttributeValue("AXValue"), "peach", "After popup value correct");
"Value of combobox did not change when it was opened"
);
todo_is(box.getAttributeValue("AXValue"), "peach");
} else {
ok(
!didBoxValueChange,
"Value of combobox did not change when it was opened"
);
is(box.getAttributeValue("AXValue"), "peach", "After popup value correct");
}
} }
addAccessibleTask( addAccessibleTask(
@ -74,8 +64,21 @@ addAccessibleTask(
`, `,
async (browser, accDoc) => { async (browser, accDoc) => {
info("Test ARIA 1.0 style combobox (entry aria-owns list)"); info("Test ARIA 1.0 style combobox (entry aria-owns list)");
// XXX: Bug 1912520
await testComboBox(browser, accDoc, true); const box = getNativeInterface(accDoc, "box");
is(
box.getAttributeValue("AXChildren").length,
1,
"owned list is not relocated"
);
// XXX: Bug 1912520 - Remap from aria-owns to aria-controls
todo_is(
box.getAttributeValue("AXARIAControls").length,
1,
"box controls list"
);
await testComboBox(browser, accDoc);
} }
); );

View file

@ -72,8 +72,8 @@
this.menu = null; this.menu = null;
this.eventSeq = [ this.eventSeq = [
new invokerChecker(EVENT_HIDE, getMenu, this),
new invokerChecker(EVENT_MENUPOPUP_END, getMenu, this), new invokerChecker(EVENT_MENUPOPUP_END, getMenu, this),
new invokerChecker(EVENT_HIDE, getMenu, this),
new invokerChecker(EVENT_REORDER, getNode(aParentMenuID)), new invokerChecker(EVENT_REORDER, getNode(aParentMenuID)),
]; ];

View file

@ -8,14 +8,15 @@
// globals from there. // globals from there.
/* import-globals-from common.js */ /* import-globals-from common.js */
/* exported EVENT_ANNOUNCEMENT, EVENT_REORDER, EVENT_SCROLLING, /* exported EVENT_ANNOUNCEMENT, EVENT_ALERT, EVENT_REORDER, EVENT_SCROLLING,
EVENT_SCROLLING_END, EVENT_SHOW, EVENT_TEXT_INSERTED, EVENT_SCROLLING_END, EVENT_SHOW, EVENT_TEXT_INSERTED,
EVENT_TEXT_REMOVED, EVENT_DOCUMENT_LOAD_COMPLETE, EVENT_HIDE, EVENT_TEXT_REMOVED, EVENT_DOCUMENT_LOAD_COMPLETE, EVENT_HIDE,
EVENT_TEXT_ATTRIBUTE_CHANGED, EVENT_TEXT_CARET_MOVED, EVENT_SELECTION, EVENT_TEXT_ATTRIBUTE_CHANGED, EVENT_TEXT_CARET_MOVED, EVENT_SELECTION,
EVENT_DESCRIPTION_CHANGE, EVENT_NAME_CHANGE, EVENT_STATE_CHANGE, EVENT_DESCRIPTION_CHANGE, EVENT_NAME_CHANGE, EVENT_STATE_CHANGE,
EVENT_VALUE_CHANGE, EVENT_TEXT_VALUE_CHANGE, EVENT_FOCUS, EVENT_VALUE_CHANGE, EVENT_TEXT_VALUE_CHANGE, EVENT_FOCUS,
EVENT_DOCUMENT_RELOAD, EVENT_VIRTUALCURSOR_CHANGED, EVENT_ALERT, EVENT_DOCUMENT_RELOAD, EVENT_VIRTUALCURSOR_CHANGED, EVENT_ALERT,
EVENT_OBJECT_ATTRIBUTE_CHANGED, UnexpectedEvents, waitForEvent, EVENT_OBJECT_ATTRIBUTE_CHANGED, EVENT_MENUPOPUP_START, EVENT_MENUPOPUP_END,
UnexpectedEvents, waitForEvent,
waitForEvents, waitForOrderedEvents, waitForStateChange, waitForEvents, waitForOrderedEvents, waitForStateChange,
stateChangeEventArgs */ stateChangeEventArgs */
@ -52,6 +53,8 @@ const EVENT_LIVE_REGION_REMOVED = nsIAccessibleEvent.EVENT_LIVE_REGION_REMOVED;
const EVENT_OBJECT_ATTRIBUTE_CHANGED = const EVENT_OBJECT_ATTRIBUTE_CHANGED =
nsIAccessibleEvent.EVENT_OBJECT_ATTRIBUTE_CHANGED; nsIAccessibleEvent.EVENT_OBJECT_ATTRIBUTE_CHANGED;
const EVENT_INNER_REORDER = nsIAccessibleEvent.EVENT_INNER_REORDER; const EVENT_INNER_REORDER = nsIAccessibleEvent.EVENT_INNER_REORDER;
const EVENT_MENUPOPUP_START = nsIAccessibleEvent.EVENT_MENUPOPUP_START;
const EVENT_MENUPOPUP_END = nsIAccessibleEvent.EVENT_MENUPOPUP_END;
const EventsLogger = { const EventsLogger = {
enabled: false, enabled: false,

View file

@ -2474,9 +2474,6 @@ pref("privacy.webrtc.deviceGracePeriodTimeoutMs", 3600000);
// the pref to hide the icons // the pref to hide the icons
pref("privacy.webrtc.showIndicatorsOnMacos14AndAbove", true); pref("privacy.webrtc.showIndicatorsOnMacos14AndAbove", true);
// Enable Fingerprinting Protection in private windows..
pref("privacy.fingerprintingProtection.pbmode", true);
// Enable Smartblock embed placeholders // Enable Smartblock embed placeholders
#ifdef NIGHTLY_BUILD #ifdef NIGHTLY_BUILD
pref("extensions.webcompat.smartblockEmbeds.enabled", true); pref("extensions.webcompat.smartblockEmbeds.enabled", true);

View file

@ -208,17 +208,6 @@ const TEST_GLOBAL = {
return {}; return {};
}, },
}, },
"@mozilla.org/security/hash;1": {
createInstance() {
return {
init() {},
updateFromStream() {},
finish() {
return "0";
},
};
},
},
"@mozilla.org/updates/update-checker;1": { createInstance() {} }, "@mozilla.org/updates/update-checker;1": { createInstance() {} },
"@mozilla.org/widget/useridleservice;1": { "@mozilla.org/widget/useridleservice;1": {
getService() { getService() {

View file

@ -30,7 +30,7 @@ const createStorage = async telemetryFeed => {
// We keep the name "snippets" to avoid having to do an IndexedDB database // We keep the name "snippets" to avoid having to do an IndexedDB database
// migration. // migration.
const dbStore = new ASRouterStorage({ const dbStore = new ASRouterStorage({
storeNames: ["sectionPrefs", "snippets"], storeNames: ["snippets"],
telemetry: { telemetry: {
handleUndesiredEvent: e => telemetryFeed.SendASRouterUndesiredEvent(e), handleUndesiredEvent: e => telemetryFeed.SendASRouterUndesiredEvent(e),
}, },

View file

@ -219,17 +219,6 @@ const TEST_GLOBAL = {
return {}; return {};
}, },
}, },
"@mozilla.org/security/hash;1": {
createInstance() {
return {
init() {},
updateFromStream() {},
finish() {
return "0";
},
};
},
},
"@mozilla.org/updates/update-checker;1": { createInstance() {} }, "@mozilla.org/updates/update-checker;1": { createInstance() {} },
"@mozilla.org/widget/useridleservice;1": { "@mozilla.org/widget/useridleservice;1": {
getService() { getService() {

View file

@ -212,25 +212,45 @@ add_task(async function testRecentlyClosedRestoreAllTabs() {
"https://example.com/", "https://example.com/",
"https://example.org/", "https://example.org/",
]; ];
const closedTabGroupUrls = ["about:logo", "about:mozilla"];
const closedTabGroupId = "1234567890-1";
const windowState = { const windowState = {
tabs: [ tabs: [
{ {
entries: [{ url: "about:mozilla", triggeringPrincipal_base64 }], entries: [{ url: "about:mozilla", triggeringPrincipal_base64 }],
}, },
], ],
_closedTabs: closedTabUrls.map(url => { _closedTabs: closedTabUrls.map(url => ({
return { title: url,
title: url, state: {
state: { entries: [
entries: [ {
{ url,
url, triggeringPrincipal_base64,
triggeringPrincipal_base64, },
}, ],
], },
}, })),
}; closedGroups: [
}), {
collapsed: false,
color: "blue",
id: closedTabGroupId,
name: "",
tabs: closedTabGroupUrls.map(url => ({
title: url,
state: {
entries: [
{
url,
triggeringPrincipal_base64,
},
],
groupId: closedTabGroupId,
},
})),
},
],
}; };
await SessionStoreTestUtils.promiseBrowserState({ await SessionStoreTestUtils.promiseBrowserState({
windows: [windowState], windows: [windowState],
@ -280,9 +300,19 @@ add_task(async function testRecentlyClosedRestoreAllTabs() {
is( is(
gBrowser.tabs.length, gBrowser.tabs.length,
initialTabCount + closedTabUrls.length, initialTabCount + closedTabUrls.length + closedTabGroupUrls.length,
"The expected number of closed tabs were restored" "The expected number of closed tabs were restored"
); );
is(
gBrowser.tabGroups.length,
1,
"The expected number of closed tab groups were restored"
);
is(
gBrowser.tabGroups[0].tabs.length,
2,
"The expected number of tabs were restored to the tab group"
);
// clean up extra tabs // clean up extra tabs
while (gBrowser.tabs.length > 1) { while (gBrowser.tabs.length > 1) {

View file

@ -137,7 +137,6 @@ for (const type of [
"SECTION_DEREGISTER", "SECTION_DEREGISTER",
"SECTION_DISABLE", "SECTION_DISABLE",
"SECTION_ENABLE", "SECTION_ENABLE",
"SECTION_MOVE",
"SECTION_OPTIONS_CHANGED", "SECTION_OPTIONS_CHANGED",
"SECTION_REGISTER", "SECTION_REGISTER",
"SECTION_UPDATE", "SECTION_UPDATE",
@ -183,7 +182,6 @@ for (const type of [
"UNINIT", "UNINIT",
"UPDATE_PINNED_SEARCH_SHORTCUTS", "UPDATE_PINNED_SEARCH_SHORTCUTS",
"UPDATE_SEARCH_SHORTCUTS", "UPDATE_SEARCH_SHORTCUTS",
"UPDATE_SECTION_PREFS",
"WALLPAPERS_CATEGORY_SET", "WALLPAPERS_CATEGORY_SET",
"WALLPAPERS_FEATURE_HIGHLIGHT_COUNTER_INCREMENT", "WALLPAPERS_FEATURE_HIGHLIGHT_COUNTER_INCREMENT",
"WALLPAPERS_FEATURE_HIGHLIGHT_CTA_CLICKED", "WALLPAPERS_FEATURE_HIGHLIGHT_CTA_CLICKED",

View file

@ -32,7 +32,7 @@ main {
padding: 0; padding: 0;
&.newtab-main { &.newtab-main {
align-items: center; min-width: min-content;
} }
.vertical-center-wrapper { .vertical-center-wrapper {

View file

@ -35,6 +35,14 @@ function getLayoutData(responsiveLayouts, index) {
layoutData.classNames.push( layoutData.classNames.push(
`col-${layout.columnCount}-position-${tileIndex}` `col-${layout.columnCount}-position-${tileIndex}`
); );
// The API tells us whether the tile should show the excerpt or not.
// Apply extra styles accordingly.
if (tile.hasExcerpt) {
layoutData.classNames.push(`col-${layout.columnCount}-show-excerpt`);
} else {
layoutData.classNames.push(`col-${layout.columnCount}-hide-excerpt`);
}
} }
}); });
}); });

View file

@ -61,10 +61,6 @@
-webkit-line-clamp: 4; -webkit-line-clamp: 4;
} }
.info-wrap .excerpt {
display: none;
}
.sections-card-footer { .sections-card-footer {
margin-block-start: var(--space-xxsmall); margin-block-start: var(--space-xxsmall);
} }
@ -409,6 +405,18 @@
.col-1-large { .col-1-large {
@include section-card-large; @include section-card-large;
} }
.col-1-hide-excerpt {
.info-wrap .excerpt {
display: none;
}
}
.col-1-show-excerpt {
.info-wrap .excerpt {
display: flex;
}
}
} }
@media (min-width: $break-point-layout-variant) { @media (min-width: $break-point-layout-variant) {
@ -431,6 +439,18 @@
.col-2-large { .col-2-large {
@include section-card-large; @include section-card-large;
} }
.col-2-hide-excerpt {
.info-wrap .excerpt {
display: none;
}
}
.col-2-show-excerpt {
.info-wrap .excerpt {
display: flex;
}
}
} }
@media (min-width: $break-point-widest) { @media (min-width: $break-point-widest) {
@ -454,6 +474,18 @@
.col-3-large { .col-3-large {
@include section-card-large; @include section-card-large;
} }
.col-3-hide-excerpt {
.info-wrap .excerpt {
display: none;
}
}
.col-3-show-excerpt {
.info-wrap .excerpt {
display: flex;
}
}
} }
@ -477,5 +509,17 @@
.col-4-large { .col-4-large {
@include section-card-large; @include section-card-large;
} }
.col-4-hide-excerpt {
.info-wrap .excerpt {
display: none;
}
}
.col-4-show-excerpt {
.info-wrap .excerpt {
display: flex;
}
}
} }
} }

View file

@ -360,6 +360,7 @@ export class TopSiteLink extends React.PureComponent {
onClick={onClick} onClick={onClick}
draggable={true} draggable={true}
data-is-sponsored-link={!!link.sponsored_tile_id} data-is-sponsored-link={!!link.sponsored_tile_id}
title={title}
> >
<div className="tile" aria-hidden={true}> <div className="tile" aria-hidden={true}>
<div <div
@ -391,7 +392,11 @@ export class TopSiteLink extends React.PureComponent {
: "" : ""
}`} }`}
> >
<span dir="auto" {...(isAddButton && { ...addButtonl10n })}> <span
className="title-label"
dir="auto"
{...(isAddButton && { ...addButtonl10n })}
>
{link.isPinned && <div className="icon icon-pin-small" />} {link.isPinned && <div className="icon icon-pin-small" />}
{title || <br />} {title || <br />}
</span> </span>
@ -583,7 +588,7 @@ export class TopSite extends React.PureComponent {
const { props } = this; const { props } = this;
const { link } = props; const { link } = props;
const isContextMenuOpen = props.activeIndex === props.index; const isContextMenuOpen = props.activeIndex === props.index;
const title = link.label || link.hostname; const title = link.label || link.title || link.hostname;
let menuOptions; let menuOptions;
if (link.sponsored_position) { if (link.sponsored_position) {
menuOptions = TOP_SITES_SPONSORED_POSITION_CONTEXT_MENU_OPTIONS; menuOptions = TOP_SITES_SPONSORED_POSITION_CONTEXT_MENU_OPTIONS;

View file

@ -718,17 +718,21 @@ $calculated-max-width-twice-widest: $break-point-widest + 2 * $card-width;
white-space: nowrap; white-space: nowrap;
min-height: 20px; min-height: 20px;
width: 100px; width: 100px;
padding: 0 var(--space-xsmall);
} }
&:hover, &:hover,
&:focus-within { &:focus-within {
span[dir='auto'] { .title:not(.sponsored) {
overflow: unset; .sponsored-label {
text-overflow: clip; display: none;
white-space: normal; }
text-wrap: balance;
contain: size; .title-label {
word-break: break-all; -webkit-line-clamp: 2;
white-space: wrap;
word-break: break-all;
}
} }
} }
} }

View file

@ -481,7 +481,7 @@ main {
padding: 0; padding: 0;
} }
main.newtab-main { main.newtab-main {
align-items: center; min-width: min-content;
} }
main .vertical-center-wrapper { main .vertical-center-wrapper {
margin: auto 0; margin: auto 0;
@ -1345,13 +1345,14 @@ main section {
white-space: nowrap; white-space: nowrap;
min-height: 20px; min-height: 20px;
width: 100px; width: 100px;
padding: 0 var(--space-xsmall);
} }
.top-sites-list .top-site-outer:hover span[dir=auto], .top-sites-list .top-site-outer:focus-within span[dir=auto] { .top-sites-list .top-site-outer:hover .title:not(.sponsored) .sponsored-label, .top-sites-list .top-site-outer:focus-within .title:not(.sponsored) .sponsored-label {
overflow: unset; display: none;
text-overflow: clip; }
white-space: normal; .top-sites-list .top-site-outer:hover .title:not(.sponsored) .title-label, .top-sites-list .top-site-outer:focus-within .title:not(.sponsored) .title-label {
text-wrap: balance; -webkit-line-clamp: 2;
contain: size; white-space: wrap;
word-break: break-all; word-break: break-all;
} }
@ -4884,9 +4885,6 @@ main section {
margin-block: var(--space-xsmall) 0; margin-block: var(--space-xsmall) 0;
-webkit-line-clamp: 4; -webkit-line-clamp: 4;
} }
.ds-section-grid.ds-card-grid .col-1-small .meta .info-wrap .excerpt {
display: none;
}
.ds-section-grid.ds-card-grid .col-1-small .meta .sections-card-footer { .ds-section-grid.ds-card-grid .col-1-small .meta .sections-card-footer {
margin-block-start: var(--space-xxsmall); margin-block-start: var(--space-xxsmall);
} }
@ -4979,6 +4977,16 @@ main section {
inset-inline-start: 0; inset-inline-start: 0;
} }
} }
@media (min-width: 610px) {
.ds-section-grid.ds-card-grid .col-1-hide-excerpt .info-wrap .excerpt {
display: none;
}
}
@media (min-width: 610px) {
.ds-section-grid.ds-card-grid .col-1-show-excerpt .info-wrap .excerpt {
display: flex;
}
}
@media (min-width: 724px) { @media (min-width: 724px) {
.ds-section-grid.ds-card-grid { .ds-section-grid.ds-card-grid {
grid-template-columns: repeat(2, 300px); grid-template-columns: repeat(2, 300px);
@ -5055,9 +5063,6 @@ main section {
margin-block: var(--space-xsmall) 0; margin-block: var(--space-xsmall) 0;
-webkit-line-clamp: 4; -webkit-line-clamp: 4;
} }
.ds-section-grid.ds-card-grid .col-2-small .meta .info-wrap .excerpt {
display: none;
}
.ds-section-grid.ds-card-grid .col-2-small .meta .sections-card-footer { .ds-section-grid.ds-card-grid .col-2-small .meta .sections-card-footer {
margin-block-start: var(--space-xxsmall); margin-block-start: var(--space-xxsmall);
} }
@ -5150,6 +5155,16 @@ main section {
inset-inline-start: 0; inset-inline-start: 0;
} }
} }
@media (min-width: 724px) {
.ds-section-grid.ds-card-grid .col-2-hide-excerpt .info-wrap .excerpt {
display: none;
}
}
@media (min-width: 724px) {
.ds-section-grid.ds-card-grid .col-2-show-excerpt .info-wrap .excerpt {
display: flex;
}
}
@media (min-width: 1122px) { @media (min-width: 1122px) {
.ds-section-grid.ds-card-grid { .ds-section-grid.ds-card-grid {
grid-template-columns: repeat(3, 300px); grid-template-columns: repeat(3, 300px);
@ -5227,9 +5242,6 @@ main section {
margin-block: var(--space-xsmall) 0; margin-block: var(--space-xsmall) 0;
-webkit-line-clamp: 4; -webkit-line-clamp: 4;
} }
.ds-section-grid.ds-card-grid .col-3-small .meta .info-wrap .excerpt {
display: none;
}
.ds-section-grid.ds-card-grid .col-3-small .meta .sections-card-footer { .ds-section-grid.ds-card-grid .col-3-small .meta .sections-card-footer {
margin-block-start: var(--space-xxsmall); margin-block-start: var(--space-xxsmall);
} }
@ -5322,6 +5334,16 @@ main section {
inset-inline-start: 0; inset-inline-start: 0;
} }
} }
@media (min-width: 1122px) {
.ds-section-grid.ds-card-grid .col-3-hide-excerpt .info-wrap .excerpt {
display: none;
}
}
@media (min-width: 1122px) {
.ds-section-grid.ds-card-grid .col-3-show-excerpt .info-wrap .excerpt {
display: flex;
}
}
@media (min-width: 1390px) { @media (min-width: 1390px) {
.ds-section-grid.ds-card-grid { .ds-section-grid.ds-card-grid {
grid-template-columns: repeat(4, 300px); grid-template-columns: repeat(4, 300px);
@ -5398,9 +5420,6 @@ main section {
margin-block: var(--space-xsmall) 0; margin-block: var(--space-xsmall) 0;
-webkit-line-clamp: 4; -webkit-line-clamp: 4;
} }
.ds-section-grid.ds-card-grid .col-4-small .meta .info-wrap .excerpt {
display: none;
}
.ds-section-grid.ds-card-grid .col-4-small .meta .sections-card-footer { .ds-section-grid.ds-card-grid .col-4-small .meta .sections-card-footer {
margin-block-start: var(--space-xxsmall); margin-block-start: var(--space-xxsmall);
} }
@ -5493,6 +5512,16 @@ main section {
inset-inline-start: 0; inset-inline-start: 0;
} }
} }
@media (min-width: 1390px) {
.ds-section-grid.ds-card-grid .col-4-hide-excerpt .info-wrap .excerpt {
display: none;
}
}
@media (min-width: 1390px) {
.ds-section-grid.ds-card-grid .col-4-show-excerpt .info-wrap .excerpt {
display: flex;
}
}
.ds-dismiss.ds-dismiss-ds-collection .ds-dismiss-button { .ds-dismiss.ds-dismiss-ds-collection .ds-dismiss-button {
margin: 15px 0 0; margin: 15px 0 0;

View file

@ -210,7 +210,6 @@ for (const type of [
"SECTION_DEREGISTER", "SECTION_DEREGISTER",
"SECTION_DISABLE", "SECTION_DISABLE",
"SECTION_ENABLE", "SECTION_ENABLE",
"SECTION_MOVE",
"SECTION_OPTIONS_CHANGED", "SECTION_OPTIONS_CHANGED",
"SECTION_REGISTER", "SECTION_REGISTER",
"SECTION_UPDATE", "SECTION_UPDATE",
@ -256,7 +255,6 @@ for (const type of [
"UNINIT", "UNINIT",
"UPDATE_PINNED_SEARCH_SHORTCUTS", "UPDATE_PINNED_SEARCH_SHORTCUTS",
"UPDATE_SEARCH_SHORTCUTS", "UPDATE_SEARCH_SHORTCUTS",
"UPDATE_SECTION_PREFS",
"WALLPAPERS_CATEGORY_SET", "WALLPAPERS_CATEGORY_SET",
"WALLPAPERS_FEATURE_HIGHLIGHT_COUNTER_INCREMENT", "WALLPAPERS_FEATURE_HIGHLIGHT_COUNTER_INCREMENT",
"WALLPAPERS_FEATURE_HIGHLIGHT_CTA_CLICKED", "WALLPAPERS_FEATURE_HIGHLIGHT_CTA_CLICKED",
@ -8121,7 +8119,8 @@ class TopSiteLink extends (external_React_default()).PureComponent {
onKeyPress: this.onKeyPress, onKeyPress: this.onKeyPress,
onClick: onClick, onClick: onClick,
draggable: true, draggable: true,
"data-is-sponsored-link": !!link.sponsored_tile_id "data-is-sponsored-link": !!link.sponsored_tile_id,
title: title
}, /*#__PURE__*/external_React_default().createElement("div", { }, /*#__PURE__*/external_React_default().createElement("div", {
className: "tile", className: "tile",
"aria-hidden": true "aria-hidden": true
@ -8143,6 +8142,7 @@ class TopSiteLink extends (external_React_default()).PureComponent {
})), /*#__PURE__*/external_React_default().createElement("div", { })), /*#__PURE__*/external_React_default().createElement("div", {
className: `title${link.isPinned ? " has-icon pinned" : ""}${link.type === SPOC_TYPE || link.show_sponsored_label ? " sponsored" : ""}` className: `title${link.isPinned ? " has-icon pinned" : ""}${link.type === SPOC_TYPE || link.show_sponsored_label ? " sponsored" : ""}`
}, /*#__PURE__*/external_React_default().createElement("span", TopSite_extends({ }, /*#__PURE__*/external_React_default().createElement("span", TopSite_extends({
className: "title-label",
dir: "auto" dir: "auto"
}, isAddButton && { }, isAddButton && {
...addButtonl10n ...addButtonl10n
@ -8321,7 +8321,7 @@ class TopSite extends (external_React_default()).PureComponent {
link link
} = props; } = props;
const isContextMenuOpen = props.activeIndex === props.index; const isContextMenuOpen = props.activeIndex === props.index;
const title = link.label || link.hostname; const title = link.label || link.title || link.hostname;
let menuOptions; let menuOptions;
if (link.sponsored_position) { if (link.sponsored_position) {
menuOptions = TOP_SITES_SPONSORED_POSITION_CONTEXT_MENU_OPTIONS; menuOptions = TOP_SITES_SPONSORED_POSITION_CONTEXT_MENU_OPTIONS;
@ -10006,6 +10006,14 @@ function getLayoutData(responsiveLayouts, index) {
if (tile.position === index) { if (tile.position === index) {
layoutData.classNames.push(`col-${layout.columnCount}-${tile.size}`); layoutData.classNames.push(`col-${layout.columnCount}-${tile.size}`);
layoutData.classNames.push(`col-${layout.columnCount}-position-${tileIndex}`); layoutData.classNames.push(`col-${layout.columnCount}-position-${tileIndex}`);
// The API tells us whether the tile should show the excerpt or not.
// Apply extra styles accordingly.
if (tile.hasExcerpt) {
layoutData.classNames.push(`col-${layout.columnCount}-show-excerpt`);
} else {
layoutData.classNames.push(`col-${layout.columnCount}-hide-excerpt`);
}
} }
}); });
}); });

View file

@ -15,7 +15,7 @@ const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, { ChromeUtils.defineESModuleGetters(lazy, {
DownloadsManager: "resource://activity-stream/lib/DownloadsManager.sys.mjs", DownloadsManager: "resource://activity-stream/lib/DownloadsManager.sys.mjs",
FilterAdult: "resource://activity-stream/lib/FilterAdult.sys.mjs", FilterAdult: "resource:///modules/FilterAdult.sys.mjs",
LinksCache: "resource://activity-stream/lib/LinksCache.sys.mjs", LinksCache: "resource://activity-stream/lib/LinksCache.sys.mjs",
NewTabUtils: "resource://gre/modules/NewTabUtils.sys.mjs", NewTabUtils: "resource://gre/modules/NewTabUtils.sys.mjs",
PageThumbs: "resource://gre/modules/PageThumbs.sys.mjs", PageThumbs: "resource://gre/modules/PageThumbs.sys.mjs",

View file

@ -119,8 +119,6 @@ export class PrefsFeed {
lazy.NimbusFeatures.newtab.onUpdate(this.onExperimentUpdated); lazy.NimbusFeatures.newtab.onUpdate(this.onExperimentUpdated);
lazy.NimbusFeatures.pocketNewtab.onUpdate(this.onPocketExperimentUpdated); lazy.NimbusFeatures.pocketNewtab.onUpdate(this.onPocketExperimentUpdated);
this._storage = this.store.dbStorage.getDbTable("sectionPrefs");
// Get the initial value of each activity stream pref // Get the initial value of each activity stream pref
const values = {}; const values = {};
for (const name of this._prefMap.keys()) { for (const name of this._prefMap.keys()) {
@ -229,15 +227,6 @@ export class PrefsFeed {
} }
} }
async _setIndexedDBPref(id, value) {
const name = id === "topsites" ? id : `feeds.section.${id}`;
try {
await this._storage.set(name, value);
} catch (e) {
console.error("Could not set section preferences.");
}
}
observe(subject, topic) { observe(subject, topic) {
switch (topic) { switch (topic) {
case lazy.Region.REGION_TOPIC: case lazy.Region.REGION_TOPIC:
@ -265,9 +254,6 @@ export class PrefsFeed {
case at.SET_PREF: case at.SET_PREF:
this._prefs.set(action.data.name, action.data.value); this._prefs.set(action.data.name, action.data.value);
break; break;
case at.UPDATE_SECTION_PREFS:
this._setIndexedDBPref(action.data.id, action.data.value);
break;
} }
} }
} }

View file

@ -16,7 +16,6 @@ import {
actionCreators as ac, actionCreators as ac,
actionTypes as at, actionTypes as at,
} from "resource://activity-stream/common/Actions.mjs"; } from "resource://activity-stream/common/Actions.mjs";
import { getDefaultOptions } from "resource:///modules/asrouter/ASRouterStorage.sys.mjs";
const lazy = {}; const lazy = {};
@ -202,8 +201,7 @@ export const SectionsManager = {
}, },
initialized: false, initialized: false,
sections: new Map(), sections: new Map(),
async init(prefs = {}, storage) { async init(prefs = {}) {
this._storage = storage;
const featureConfig = { const featureConfig = {
newtab: lazy.NimbusFeatures.newtab.getAllVariables() || {}, newtab: lazy.NimbusFeatures.newtab.getAllVariables() || {},
pocketNewtab: lazy.NimbusFeatures.pocketNewtab.getAllVariables() || {}, pocketNewtab: lazy.NimbusFeatures.pocketNewtab.getAllVariables() || {},
@ -242,20 +240,8 @@ export const SectionsManager = {
break; break;
} }
}, },
updateSectionPrefs(id, collapsed) {
const section = this.sections.get(id);
if (!section) {
return;
}
const updatedSection = Object.assign({}, section, {
pref: Object.assign({}, section.pref, collapsed),
});
this.updateSection(id, updatedSection, true);
},
async addBuiltInSection(feedPrefName, optionsPrefValue = "{}") { async addBuiltInSection(feedPrefName, optionsPrefValue = "{}") {
let options; let options;
let storedPrefs;
const featureConfig = { const featureConfig = {
newtab: lazy.NimbusFeatures.newtab.getAllVariables() || {}, newtab: lazy.NimbusFeatures.newtab.getAllVariables() || {},
pocketNewtab: lazy.NimbusFeatures.pocketNewtab.getAllVariables() || {}, pocketNewtab: lazy.NimbusFeatures.pocketNewtab.getAllVariables() || {},
@ -266,20 +252,11 @@ export const SectionsManager = {
options = {}; options = {};
console.error(`Problem parsing options pref for ${feedPrefName}`); console.error(`Problem parsing options pref for ${feedPrefName}`);
} }
try {
storedPrefs = (await this._storage.get(feedPrefName)) || {};
} catch (e) {
storedPrefs = {};
console.error(`Problem getting stored prefs for ${feedPrefName}`);
}
const defaultSection = const defaultSection =
BUILT_IN_SECTIONS(featureConfig)[feedPrefName](options); BUILT_IN_SECTIONS(featureConfig)[feedPrefName](options);
const section = Object.assign({}, defaultSection, { const section = Object.assign({}, defaultSection, {
pref: Object.assign( pref: Object.assign({}, defaultSection.pref),
{},
defaultSection.pref,
getDefaultOptions(storedPrefs)
),
}); });
section.pref.feed = feedPrefName; section.pref.feed = feedPrefName;
this.addSection(section.id, Object.assign(section, { options })); this.addSection(section.id, Object.assign(section, { options }));
@ -602,48 +579,6 @@ export class SectionsFeed {
return this.store.getState().Prefs.values.sectionOrder.split(","); return this.store.getState().Prefs.values.sectionOrder.split(",");
} }
get enabledSectionIds() {
let sections = this.store
.getState()
.Sections.filter(section => section.enabled)
.map(s => s.id);
// Top Sites is a special case. Append if the feed is enabled.
if (this.store.getState().Prefs.values["feeds.topsites"]) {
sections.push("topsites");
}
return sections;
}
moveSection(id, direction) {
const orderedSections = this.orderedSectionIds;
const enabledSections = this.enabledSectionIds;
let index = orderedSections.indexOf(id);
orderedSections.splice(index, 1);
if (direction > 0) {
// "Move Down"
while (index < orderedSections.length) {
// If the section at the index is enabled/visible, insert moved section after.
// Otherwise, move on to the next spot and check it.
if (enabledSections.includes(orderedSections[index++])) {
break;
}
}
} else {
// "Move Up"
while (index > 0) {
// If the section at the previous index is enabled/visible, insert moved section there.
// Otherwise, move on to the previous spot and check it.
index--;
if (enabledSections.includes(orderedSections[index])) {
break;
}
}
}
orderedSections.splice(index, 0, id);
this.store.dispatch(ac.SetPref("sectionOrder", orderedSections.join(",")));
}
async onAction(action) { async onAction(action) {
switch (action.type) { switch (action.type) {
case at.INIT: case at.INIT:
@ -651,10 +586,7 @@ export class SectionsFeed {
break; break;
// Wait for pref values, as some sections have options stored in prefs // Wait for pref values, as some sections have options stored in prefs
case at.PREFS_INITIAL_VALUES: case at.PREFS_INITIAL_VALUES:
SectionsManager.init( SectionsManager.init(action.data);
action.data,
this.store.dbStorage.getDbTable("sectionPrefs")
);
break; break;
case at.PREF_CHANGED: { case at.PREF_CHANGED: {
if (action.data) { if (action.data) {
@ -674,9 +606,6 @@ export class SectionsFeed {
} }
break; break;
} }
case at.UPDATE_SECTION_PREFS:
SectionsManager.updateSectionPrefs(action.data.id, action.data.value);
break;
case at.PLACES_BOOKMARK_ADDED: case at.PLACES_BOOKMARK_ADDED:
SectionsManager.updateBookmarkMetadata(action.data); SectionsManager.updateBookmarkMetadata(action.data);
break; break;
@ -694,9 +623,6 @@ export class SectionsFeed {
case at.SECTION_ENABLE: case at.SECTION_ENABLE:
SectionsManager.enableSection(action.data); SectionsManager.enableSection(action.data);
break; break;
case at.SECTION_MOVE:
this.moveSection(action.data.id, action.data.direction);
break;
case at.UNINIT: case at.UNINIT:
this.uninit(); this.uninit();
break; break;

View file

@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import { ActivityStreamMessageChannel } from "resource://activity-stream/lib/ActivityStreamMessageChannel.sys.mjs"; import { ActivityStreamMessageChannel } from "resource://activity-stream/lib/ActivityStreamMessageChannel.sys.mjs";
import { ASRouterStorage } from "resource:///modules/asrouter/ASRouterStorage.sys.mjs";
import { Prefs } from "resource://activity-stream/lib/ActivityStreamPrefs.sys.mjs"; import { Prefs } from "resource://activity-stream/lib/ActivityStreamPrefs.sys.mjs";
import { reducers } from "resource://activity-stream/common/Reducers.sys.mjs"; import { reducers } from "resource://activity-stream/common/Reducers.sys.mjs";
import { redux } from "chrome://global/content/vendor/Redux.sys.mjs"; import { redux } from "chrome://global/content/vendor/Redux.sys.mjs";
@ -36,7 +35,6 @@ export class Store {
redux.combineReducers(reducers), redux.combineReducers(reducers),
redux.applyMiddleware(this._middleware, this._messageChannel.middleware) redux.applyMiddleware(this._middleware, this._messageChannel.middleware)
); );
this.storage = null;
} }
/** /**
@ -125,8 +123,6 @@ export class Store {
this.initFeed(telemetryKey); this.initFeed(telemetryKey);
} }
await this._initIndexedDB(telemetryKey);
for (const pref of feedFactories.keys()) { for (const pref of feedFactories.keys()) {
if (pref !== telemetryKey && this._prefs.get(pref)) { if (pref !== telemetryKey && this._prefs.get(pref)) {
this.initFeed(pref); this.initFeed(pref);
@ -144,26 +140,6 @@ export class Store {
this._messageChannel.simulateMessagesForExistingTabs(); this._messageChannel.simulateMessagesForExistingTabs();
} }
async _initIndexedDB() {
// "snippets" is the name of one storage space, but these days it is used
// not for snippet-related data (snippets were removed in bug 1715158),
// but storage for impression or session data for all ASRouter messages.
//
// We keep the name "snippets" to avoid having to do an IndexedDB database
// migration.
this.dbStorage = new ASRouterStorage({
storeNames: ["sectionPrefs", "snippets"],
});
// Accessing the db causes the object stores to be created / migrated.
// This needs to happen before other instances try to access the db, which
// would update only a subset of the stores to the latest version.
try {
await this.dbStorage.db; // eslint-disable-line no-unused-expressions
} catch (e) {
this.dbStorage.telemetry = null;
}
}
/** /**
* uninit - Uninitalizes each feed, clears them, and destroys the message * uninit - Uninitalizes each feed, clears them, and destroys the message
* manager channel. * manager channel.

View file

@ -51,6 +51,7 @@ export const PREF_UNIFIED_ADS_TILES_ENABLED = "unifiedAds.tiles.enabled";
const PREF_ENDPOINTS = "discoverystream.endpoints"; const PREF_ENDPOINTS = "discoverystream.endpoints";
const PREF_SHOW_SPONSORED_STORIES = "showSponsored"; const PREF_SHOW_SPONSORED_STORIES = "showSponsored";
const PREF_SHOW_SPONSORED_TOPSITES = "showSponsoredTopSites"; const PREF_SHOW_SPONSORED_TOPSITES = "showSponsoredTopSites";
const BLANK_HOMEPAGE_URL = "chrome://browser/content/blanktab.html";
// This is a mapping table between the user preferences and its encoding code // This is a mapping table between the user preferences and its encoding code
export const USER_PREFS_ENCODING = { export const USER_PREFS_ENCODING = {
@ -839,7 +840,9 @@ export class TelemetryFeed {
const homePageURL = lazy.HomePage.get(); const homePageURL = lazy.HomePage.get();
if ( if (
!["about:home", "about:blank"].includes(homePageURL) && !["about:home", "about:blank", BLANK_HOMEPAGE_URL].includes(
homePageURL
) &&
!homePageURL.startsWith("moz-extension://") !homePageURL.startsWith("moz-extension://")
) { ) {
value.home_url_category = await this._classifySite(homePageURL); value.home_url_category = await this._classifySite(homePageURL);

View file

@ -16,7 +16,6 @@ import {
shortURL, shortURL,
shortHostname, shortHostname,
} from "resource://activity-stream/lib/ShortURL.sys.mjs"; } from "resource://activity-stream/lib/ShortURL.sys.mjs";
import { getDefaultOptions } from "resource:///modules/asrouter/ASRouterStorage.sys.mjs";
import { import {
CUSTOM_SEARCH_SHORTCUTS, CUSTOM_SEARCH_SHORTCUTS,
@ -30,7 +29,7 @@ import {
const lazy = {}; const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, { ChromeUtils.defineESModuleGetters(lazy, {
FilterAdult: "resource://activity-stream/lib/FilterAdult.sys.mjs", FilterAdult: "resource:///modules/FilterAdult.sys.mjs",
LinksCache: "resource://activity-stream/lib/LinksCache.sys.mjs", LinksCache: "resource://activity-stream/lib/LinksCache.sys.mjs",
NewTabUtils: "resource://gre/modules/NewTabUtils.sys.mjs", NewTabUtils: "resource://gre/modules/NewTabUtils.sys.mjs",
NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs", NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs",
@ -71,7 +70,7 @@ const PINNED_FAVICON_PROPS_TO_MIGRATE = [
"faviconRef", "faviconRef",
"faviconSize", "faviconSize",
]; ];
const SECTION_ID = "topsites";
const CACHE_KEY = "contile"; const CACHE_KEY = "contile";
const ROWS_PREF = "topSitesRows"; const ROWS_PREF = "topSitesRows";
const SHOW_SPONSORED_PREF = "showSponsoredTopSites"; const SHOW_SPONSORED_PREF = "showSponsoredTopSites";
@ -746,7 +745,6 @@ export class TopSitesFeed {
init() { init() {
// If the feed was previously disabled PREFS_INITIAL_VALUES was never received // If the feed was previously disabled PREFS_INITIAL_VALUES was never received
this._readDefaults({ isStartup: true }); this._readDefaults({ isStartup: true });
this._storage = this.store.dbStorage.getDbTable("sectionPrefs");
this._contile.refresh(); this._contile.refresh();
Services.obs.addObserver(this, "browser-search-engine-modified"); Services.obs.addObserver(this, "browser-search-engine-modified");
Services.obs.addObserver(this, "browser-region-updated"); Services.obs.addObserver(this, "browser-region-updated");
@ -1609,14 +1607,6 @@ export class TopSitesFeed {
isStartup: options.isStartup, isStartup: options.isStartup,
}); });
const newAction = { type: at.TOP_SITES_UPDATED, data: { links } }; const newAction = { type: at.TOP_SITES_UPDATED, data: { links } };
let storedPrefs;
try {
storedPrefs = (await this._storage.get(SECTION_ID)) || {};
} catch (e) {
storedPrefs = {};
console.error("Problem getting stored prefs for TopSites");
}
newAction.data.pref = getDefaultOptions(storedPrefs);
if (options.isStartup) { if (options.isStartup) {
newAction.meta = { newAction.meta = {
@ -1794,15 +1784,6 @@ export class TopSitesFeed {
}); });
} }
updateSectionPrefs(collapsed) {
this.store.dispatch(
ac.BroadcastToContent({
type: at.TOP_SITES_PREFS_UPDATED,
data: { pref: collapsed },
})
);
}
/** /**
* Inform others that top sites data has been updated due to pinned changes. * Inform others that top sites data has been updated due to pinned changes.
*/ */
@ -2107,11 +2088,6 @@ export class TopSitesFeed {
break; break;
} }
break; break;
case at.UPDATE_SECTION_PREFS:
if (action.data.id === SECTION_ID) {
this.updateSectionPrefs(action.data.value);
}
break;
case at.PREFS_INITIAL_VALUES: case at.PREFS_INITIAL_VALUES:
if (!this._useRemoteSetting) { if (!this._useRemoteSetting) {
this.refreshDefaults(action.data[DEFAULT_SITES_PREF]); this.refreshDefaults(action.data[DEFAULT_SITES_PREF]);

View file

@ -180,8 +180,30 @@ describe("<CardSections />", () => {
it("should apply correct classNames and position from layout data", () => { it("should apply correct classNames and position from layout data", () => {
const props = wrapper.find(DSCard).at(0).props(); const props = wrapper.find(DSCard).at(0).props();
const thirdProps = wrapper.find(DSCard).at(2).props(); const thirdProps = wrapper.find(DSCard).at(2).props();
assert.equal(props.sectionsClassNames, "col-1-large col-1-position-0"); assert.equal(
assert.equal(thirdProps.sectionsClassNames, "col-1-small col-1-position-1"); props.sectionsClassNames,
"col-1-large col-1-position-0 col-1-show-excerpt"
);
assert.equal(
thirdProps.sectionsClassNames,
"col-1-small col-1-position-1 col-1-hide-excerpt"
);
});
it("should apply correct class names for cards with and without excerpts", () => {
wrapper.find(DSCard).forEach(card => {
const props = card.props();
// Small cards don't show excerpts according to the data in DEFAULT_PROPS for this test suite
if (props.sectionsClassNames.includes("small")) {
assert.include(props.sectionsClassNames, "hide-excerpt");
assert.notInclude(props.sectionsClassNames, "show-excerpt");
}
// The other cards should show excerpts though!
else {
assert.include(props.sectionsClassNames, "show-excerpt");
assert.notInclude(props.sectionsClassNames, "hide-excerpt");
}
});
}); });
it("should dispatch PREF_FOLLOWED_SECTIONS updates with follow and unfollow", () => { it("should dispatch PREF_FOLLOWED_SECTIONS updates with follow and unfollow", () => {

View file

@ -1,112 +0,0 @@
import { FilterAdult } from "lib/FilterAdult.sys.mjs";
import { GlobalOverrider } from "test/unit/utils";
describe("FilterAdult", () => {
let hashStub;
let hashValue;
let globals;
beforeEach(() => {
globals = new GlobalOverrider();
hashStub = {
finish: sinon.stub().callsFake(() => hashValue),
init: sinon.stub(),
update: sinon.stub(),
};
globals.set("Cc", {
"@mozilla.org/security/hash;1": {
createInstance() {
return hashStub;
},
},
});
globals.set("gFilterAdultEnabled", true);
});
afterEach(() => {
hashValue = "";
globals.restore();
});
describe("filter", () => {
it("should default to include on unexpected urls", () => {
const empty = {};
const result = FilterAdult.filter([empty]);
assert.equal(result.length, 1);
assert.equal(result[0], empty);
});
it("should not filter out non-adult urls", () => {
const link = { url: "https://mozilla.org/" };
const result = FilterAdult.filter([link]);
assert.equal(result.length, 1);
assert.equal(result[0], link);
});
it("should filter out adult urls", () => {
// Use a hash value that is in the adult set
hashValue = "+/UCpAhZhz368iGioEO8aQ==";
const link = { url: "https://some-adult-site/" };
const result = FilterAdult.filter([link]);
assert.equal(result.length, 0);
});
it("should not filter out adult urls if the preference is turned off", () => {
// Use a hash value that is in the adult set
hashValue = "+/UCpAhZhz368iGioEO8aQ==";
globals.set("gFilterAdultEnabled", false);
const link = { url: "https://some-adult-site/" };
const result = FilterAdult.filter([link]);
assert.equal(result.length, 1);
assert.equal(result[0], link);
});
});
describe("isAdultUrl", () => {
it("should default to false on unexpected urls", () => {
const result = FilterAdult.isAdultUrl("");
assert.equal(result, false);
});
it("should return false for non-adult urls", () => {
const result = FilterAdult.isAdultUrl("https://mozilla.org/");
assert.equal(result, false);
});
it("should return true for adult urls", () => {
// Use a hash value that is in the adult set
hashValue = "+/UCpAhZhz368iGioEO8aQ==";
const result = FilterAdult.isAdultUrl("https://some-adult-site/");
assert.equal(result, true);
});
it("should return false for adult urls when the preference is turned off", () => {
// Use a hash value that is in the adult set
hashValue = "+/UCpAhZhz368iGioEO8aQ==";
globals.set("gFilterAdultEnabled", false);
const result = FilterAdult.isAdultUrl("https://some-adult-site/");
assert.equal(result, false);
});
describe("test functions", () => {
it("should add and remove a filter in the adult list", () => {
// Use a hash value that is in the adult set
FilterAdult.addDomainToList("https://some-adult-site/");
let result = FilterAdult.isAdultUrl("https://some-adult-site/");
assert.equal(result, true);
FilterAdult.removeDomainFromList("https://some-adult-site/");
result = FilterAdult.isAdultUrl("https://some-adult-site/");
assert.equal(result, false);
});
});
});
});

View file

@ -18,10 +18,6 @@ describe("PrefsFeed", () => {
["qux", { value: 1, skipBroadcast: true, alsoToPreloaded: true }], ["qux", { value: 1, skipBroadcast: true, alsoToPreloaded: true }],
]); ]);
feed = new PrefsFeed(FAKE_PREFS); feed = new PrefsFeed(FAKE_PREFS);
const storage = {
getAll: sandbox.stub().resolves(),
set: sandbox.stub().resolves(),
};
ServicesStub = { ServicesStub = {
prefs: { prefs: {
clearUserPref: sinon.spy(), clearUserPref: sinon.spy(),
@ -40,10 +36,8 @@ describe("PrefsFeed", () => {
getState() { getState() {
return this.state; return this.state;
}, },
dbStorage: { getDbTable: sandbox.stub().returns(storage) },
}; };
// Setup for tests that don't call `init` // Setup for tests that don't call `init`
feed._storage = storage;
feed._prefs = { feed._prefs = {
get: sinon.spy(item => FAKE_PREFS.get(item)), get: sinon.spy(item => FAKE_PREFS.get(item)),
set: sinon.spy((name, value) => FAKE_PREFS.set(name, value)), set: sinon.spy((name, value) => FAKE_PREFS.set(name, value)),
@ -111,12 +105,6 @@ describe("PrefsFeed", () => {
assert.calledOnce(feed._prefs.observeBranch); assert.calledOnce(feed._prefs.observeBranch);
assert.calledWith(feed._prefs.observeBranch, feed); assert.calledWith(feed._prefs.observeBranch, feed);
}); });
it("should initialise the storage on init", () => {
feed.init();
assert.calledOnce(feed.store.dbStorage.getDbTable);
assert.calledWithExactly(feed.store.dbStorage.getDbTable, "sectionPrefs");
});
it("should handle region on init", () => { it("should handle region on init", () => {
feed.init(); feed.init();
assert.equal(feed.geo, "US"); assert.equal(feed.geo, "US");
@ -224,32 +212,6 @@ describe("PrefsFeed", () => {
global.Region.REGION_TOPIC global.Region.REGION_TOPIC
); );
}); });
it("should set storage pref on UPDATE_SECTION_PREFS", async () => {
await feed.onAction({
type: at.UPDATE_SECTION_PREFS,
data: { id: "topsites", value: { collapsed: false } },
});
assert.calledWith(feed._storage.set, "topsites", { collapsed: false });
});
it("should set storage pref with section prefix on UPDATE_SECTION_PREFS", async () => {
await feed.onAction({
type: at.UPDATE_SECTION_PREFS,
data: { id: "topstories", value: { collapsed: false } },
});
assert.calledWith(feed._storage.set, "feeds.section.topstories", {
collapsed: false,
});
});
it("should catch errors on UPDATE_SECTION_PREFS", async () => {
feed._storage.set.throws(new Error("foo"));
assert.doesNotThrow(async () => {
await feed.onAction({
type: at.UPDATE_SECTION_PREFS,
data: { id: "topstories", value: { collapsed: false } },
});
});
});
it("should send OnlyToMain pref update if config for pref has skipBroadcast: true", async () => { it("should send OnlyToMain pref update if config for pref has skipBroadcast: true", async () => {
feed.onPrefChanged("baz", { value: 2, skipBroadcast: true }); feed.onPrefChanged("baz", { value: 2, skipBroadcast: true });
assert.calledWith( assert.calledWith(

View file

@ -25,7 +25,6 @@ describe("SectionsManager", () => {
let fakeServices; let fakeServices;
let fakePlacesUtils; let fakePlacesUtils;
let sandbox; let sandbox;
let storage;
beforeEach(async () => { beforeEach(async () => {
sandbox = sinon.createSandbox(); sandbox = sinon.createSandbox();
@ -50,10 +49,6 @@ describe("SectionsManager", () => {
}); });
// Redecorate SectionsManager to remove any listeners that have been added // Redecorate SectionsManager to remove any listeners that have been added
EventEmitter.decorate(SectionsManager); EventEmitter.decorate(SectionsManager);
storage = {
get: sandbox.stub().resolves(),
set: sandbox.stub().resolves(),
};
}); });
afterEach(() => { afterEach(() => {
@ -65,7 +60,7 @@ describe("SectionsManager", () => {
it("should initialise the sections map with the built in sections", async () => { it("should initialise the sections map with the built in sections", async () => {
SectionsManager.sections.clear(); SectionsManager.sections.clear();
SectionsManager.initialized = false; SectionsManager.initialized = false;
await SectionsManager.init({}, storage); await SectionsManager.init({});
assert.equal(SectionsManager.sections.size, 2); assert.equal(SectionsManager.sections.size, 2);
assert.ok(SectionsManager.sections.has("topstories")); assert.ok(SectionsManager.sections.has("topstories"));
assert.ok(SectionsManager.sections.has("highlights")); assert.ok(SectionsManager.sections.has("highlights"));
@ -73,12 +68,12 @@ describe("SectionsManager", () => {
it("should set .initialized to true", async () => { it("should set .initialized to true", async () => {
SectionsManager.sections.clear(); SectionsManager.sections.clear();
SectionsManager.initialized = false; SectionsManager.initialized = false;
await SectionsManager.init({}, storage); await SectionsManager.init({});
assert.ok(SectionsManager.initialized); assert.ok(SectionsManager.initialized);
}); });
it("should add observer for context menu prefs", async () => { it("should add observer for context menu prefs", async () => {
SectionsManager.CONTEXT_MENU_PREFS = { MENU_ITEM: "MENU_ITEM_PREF" }; SectionsManager.CONTEXT_MENU_PREFS = { MENU_ITEM: "MENU_ITEM_PREF" };
await SectionsManager.init({}, storage); await SectionsManager.init({});
assert.calledOnce(fakeServices.prefs.addObserver); assert.calledOnce(fakeServices.prefs.addObserver);
assert.calledWith( assert.calledWith(
fakeServices.prefs.addObserver, fakeServices.prefs.addObserver,
@ -86,11 +81,6 @@ describe("SectionsManager", () => {
SectionsManager SectionsManager
); );
}); });
it("should save the reference to `storage` passed in", async () => {
await SectionsManager.init({}, storage);
assert.equal(SectionsManager._storage, storage);
});
}); });
describe("#uninit", () => { describe("#uninit", () => {
it("should remove observer for context menu prefs", () => { it("should remove observer for context menu prefs", () => {
@ -109,7 +99,6 @@ describe("SectionsManager", () => {
describe("#addBuiltInSection", () => { describe("#addBuiltInSection", () => {
it("should not report an error if options is undefined", async () => { it("should not report an error if options is undefined", async () => {
globals.sandbox.spy(global.console, "error"); globals.sandbox.spy(global.console, "error");
SectionsManager._storage.get = sandbox.stub().returns(Promise.resolve());
await SectionsManager.addBuiltInSection( await SectionsManager.addBuiltInSection(
"feeds.section.topstories", "feeds.section.topstories",
undefined undefined
@ -119,7 +108,6 @@ describe("SectionsManager", () => {
}); });
it("should report an error if options is malformed", async () => { it("should report an error if options is malformed", async () => {
globals.sandbox.spy(global.console, "error"); globals.sandbox.spy(global.console, "error");
SectionsManager._storage.get = sandbox.stub().returns(Promise.resolve());
await SectionsManager.addBuiltInSection( await SectionsManager.addBuiltInSection(
"feeds.section.topstories", "feeds.section.topstories",
"invalid" "invalid"
@ -127,40 +115,6 @@ describe("SectionsManager", () => {
assert.calledOnce(console.error); assert.calledOnce(console.error);
}); });
it("should not throw if the indexedDB operation fails", async () => {
globals.sandbox.spy(global.console, "error");
storage.get = sandbox.stub().throws();
SectionsManager._storage = storage;
try {
await SectionsManager.addBuiltInSection("feeds.section.topstories");
} catch (e) {
assert.fail();
}
assert.calledOnce(storage.get);
assert.calledOnce(console.error);
});
});
describe("#updateSectionPrefs", () => {
it("should update the collapsed value of the section", async () => {
sandbox.stub(SectionsManager, "updateSection");
let topstories = SectionsManager.sections.get("topstories");
assert.isFalse(topstories.pref.collapsed);
await SectionsManager.updateSectionPrefs("topstories", {
collapsed: true,
});
topstories = SectionsManager.sections.get("topstories");
assert.isTrue(SectionsManager.updateSection.args[0][1].pref.collapsed);
});
it("should ignore invalid ids", async () => {
sandbox.stub(SectionsManager, "updateSection");
await SectionsManager.updateSectionPrefs("foo", { collapsed: true });
assert.notCalled(SectionsManager.updateSection);
});
}); });
describe("#addSection", () => { describe("#addSection", () => {
it("should add the id to sections and emit an ADD_SECTION event", () => { it("should add the id to sections and emit an ADD_SECTION event", () => {
@ -295,7 +249,7 @@ describe("SectionsManager", () => {
SectionsManager.updateSections = sinon.spy(); SectionsManager.updateSections = sinon.spy();
SectionsManager.CONTEXT_MENU_PREFS = { MENU_ITEM: "MENU_ITEM_PREF" }; SectionsManager.CONTEXT_MENU_PREFS = { MENU_ITEM: "MENU_ITEM_PREF" };
await SectionsManager.init({}, storage); await SectionsManager.init({});
observer.observe("", "nsPref:changed", "MENU_ITEM_PREF"); observer.observe("", "nsPref:changed", "MENU_ITEM_PREF");
assert.calledOnce(SectionsManager.updateSections); assert.calledOnce(SectionsManager.updateSections);
@ -518,7 +472,6 @@ describe("SectionsManager", () => {
describe("SectionsFeed", () => { describe("SectionsFeed", () => {
let feed; let feed;
let sandbox; let sandbox;
let storage;
let globals; let globals;
beforeEach(() => { beforeEach(() => {
@ -530,10 +483,6 @@ describe("SectionsFeed", () => {
newtab: { getAllVariables: sandbox.stub() }, newtab: { getAllVariables: sandbox.stub() },
pocketNewtab: { getAllVariables: sandbox.stub() }, pocketNewtab: { getAllVariables: sandbox.stub() },
}); });
storage = {
get: sandbox.stub().resolves(),
set: sandbox.stub().resolves(),
};
feed = new SectionsFeed(); feed = new SectionsFeed();
feed.store = { dispatch: sinon.spy() }; feed.store = { dispatch: sinon.spy() };
feed.store = { feed.store = {
@ -550,7 +499,6 @@ describe("SectionsFeed", () => {
}, },
Sections: [{ initialized: false }], Sections: [{ initialized: false }],
}, },
dbStorage: { getDbTable: sandbox.stub().returns(storage) },
}; };
}); });
afterEach(() => { afterEach(() => {
@ -575,7 +523,7 @@ describe("SectionsFeed", () => {
} }
}); });
it("should call onAddSection for any already added sections in SectionsManager", async () => { it("should call onAddSection for any already added sections in SectionsManager", async () => {
await SectionsManager.init({}, storage); await SectionsManager.init({});
assert.ok(SectionsManager.sections.has("topstories")); assert.ok(SectionsManager.sections.has("topstories"));
assert.ok(SectionsManager.sections.has("highlights")); assert.ok(SectionsManager.sections.has("highlights"));
const topstories = SectionsManager.sections.get("topstories"); const topstories = SectionsManager.sections.get("topstories");
@ -721,14 +669,6 @@ describe("SectionsFeed", () => {
assert.calledOnce(SectionsManager.once); assert.calledOnce(SectionsManager.once);
assert.calledWith(SectionsManager.once, SectionsManager.INIT, feed.init); assert.calledWith(SectionsManager.once, SectionsManager.INIT, feed.init);
}); });
it("should call SectionsManager.init on action PREFS_INITIAL_VALUES", () => {
sinon.spy(SectionsManager, "init");
feed.onAction({ type: "PREFS_INITIAL_VALUES", data: { foo: "bar" } });
assert.calledOnce(SectionsManager.init);
assert.calledWith(SectionsManager.init, { foo: "bar" });
assert.calledOnce(feed.store.dbStorage.getDbTable);
assert.calledWithExactly(feed.store.dbStorage.getDbTable, "sectionPrefs");
});
it("should call SectionsManager.addBuiltInSection on suitable PREF_CHANGED events", () => { it("should call SectionsManager.addBuiltInSection on suitable PREF_CHANGED events", () => {
sinon.spy(SectionsManager, "addBuiltInSection"); sinon.spy(SectionsManager, "addBuiltInSection");
feed.onAction({ feed.onAction({
@ -802,13 +742,6 @@ describe("SectionsFeed", () => {
assert.calledOnce(stub); assert.calledOnce(stub);
}); });
it("should call updateSectionPrefs on UPDATE_SECTION_PREFS", () => {
const stub = sinon.stub(SectionsManager, "updateSectionPrefs");
feed.onAction({ type: "UPDATE_SECTION_PREFS", data: {} });
assert.calledOnce(stub);
});
it("should call SectionManager.removeSectionCard on WEBEXT_DISMISS", () => { it("should call SectionManager.removeSectionCard on WEBEXT_DISMISS", () => {
const stub = sinon.stub(SectionsManager, "removeSectionCard"); const stub = sinon.stub(SectionsManager, "removeSectionCard");
@ -819,79 +752,5 @@ describe("SectionsFeed", () => {
assert.calledOnce(stub); assert.calledOnce(stub);
assert.calledWith(stub, "Foo", "bar.com"); assert.calledWith(stub, "Foo", "bar.com");
}); });
it("should call the feed's moveSection on SECTION_MOVE", () => {
sinon.stub(feed, "moveSection");
const id = "topsites";
const direction = +1;
feed.onAction({ type: "SECTION_MOVE", data: { id, direction } });
assert.calledOnce(feed.moveSection);
assert.calledWith(feed.moveSection, id, direction);
});
});
describe("#moveSection", () => {
it("should Move Down correctly", () => {
feed.store.state.Sections = [
{ id: "topstories", enabled: true },
{ id: "highlights", enabled: true },
];
feed.moveSection("topsites", +1);
assert.calledOnce(feed.store.dispatch);
assert.calledWith(feed.store.dispatch, {
data: { name: "sectionOrder", value: "topstories,topsites,highlights" },
meta: { from: "ActivityStream:Content", to: "ActivityStream:Main" },
type: "SET_PREF",
});
feed.store.dispatch.resetHistory();
feed.moveSection("topstories", +1);
assert.calledOnce(feed.store.dispatch);
assert.calledWith(feed.store.dispatch, {
data: { name: "sectionOrder", value: "topsites,highlights,topstories" },
meta: { from: "ActivityStream:Content", to: "ActivityStream:Main" },
type: "SET_PREF",
});
});
it("should Move Up correctly", () => {
feed.store.state.Sections = [
{ id: "topstories", enabled: true },
{ id: "highlights", enabled: true },
];
feed.moveSection("topstories", -1);
assert.calledOnce(feed.store.dispatch);
assert.calledWith(feed.store.dispatch, {
data: { name: "sectionOrder", value: "topstories,topsites,highlights" },
meta: { from: "ActivityStream:Content", to: "ActivityStream:Main" },
type: "SET_PREF",
});
feed.store.dispatch.resetHistory();
feed.moveSection("highlights", -1);
assert.calledOnce(feed.store.dispatch);
assert.calledWith(feed.store.dispatch, {
data: { name: "sectionOrder", value: "topsites,highlights,topstories" },
meta: { from: "ActivityStream:Content", to: "ActivityStream:Main" },
type: "SET_PREF",
});
});
it("should skip over sections that aren't enabled", () => {
feed.store.state.Sections = [
{ id: "topstories", enabled: false },
{ id: "highlights", enabled: true },
];
feed.moveSection("highlights", -1);
assert.calledOnce(feed.store.dispatch);
assert.calledWith(feed.store.dispatch, {
data: { name: "sectionOrder", value: "highlights,topsites,topstories" },
meta: { from: "ActivityStream:Content", to: "ActivityStream:Main" },
type: "SET_PREF",
});
feed.store.dispatch.resetHistory();
feed.moveSection("topsites", +1);
assert.calledOnce(feed.store.dispatch);
assert.calledWith(feed.store.dispatch, {
data: { name: "sectionOrder", value: "topstories,highlights,topsites" },
meta: { from: "ActivityStream:Content", to: "ActivityStream:Main" },
type: "SET_PREF",
});
});
}); });
}); });

View file

@ -197,17 +197,6 @@ const TEST_GLOBAL = {
return {}; return {};
}, },
}, },
"@mozilla.org/security/hash;1": {
createInstance() {
return {
init() {},
updateFromStream() {},
finish() {
return "0";
},
};
},
},
"@mozilla.org/updates/update-checker;1": { createInstance() {} }, "@mozilla.org/updates/update-checker;1": { createInstance() {} },
"@mozilla.org/widget/useridleservice;1": { "@mozilla.org/widget/useridleservice;1": {
getService() { getService() {

View file

@ -8,7 +8,7 @@ const { actionTypes: at } = ChromeUtils.importESModule(
); );
ChromeUtils.defineESModuleGetters(this, { ChromeUtils.defineESModuleGetters(this, {
FilterAdult: "resource://activity-stream/lib/FilterAdult.sys.mjs", FilterAdult: "resource:///modules/FilterAdult.sys.mjs",
NewTabUtils: "resource://gre/modules/NewTabUtils.sys.mjs", NewTabUtils: "resource://gre/modules/NewTabUtils.sys.mjs",
PageThumbs: "resource://gre/modules/PageThumbs.sys.mjs", PageThumbs: "resource://gre/modules/PageThumbs.sys.mjs",
Screenshots: "resource://activity-stream/lib/Screenshots.sys.mjs", Screenshots: "resource://activity-stream/lib/Screenshots.sys.mjs",

View file

@ -9,9 +9,6 @@ const { Store } = ChromeUtils.importESModule(
const { ActivityStreamMessageChannel } = ChromeUtils.importESModule( const { ActivityStreamMessageChannel } = ChromeUtils.importESModule(
"resource://activity-stream/lib/ActivityStreamMessageChannel.sys.mjs" "resource://activity-stream/lib/ActivityStreamMessageChannel.sys.mjs"
); );
const { ASRouterStorage } = ChromeUtils.importESModule(
"resource:///modules/asrouter/ASRouterStorage.sys.mjs"
);
const { sinon } = ChromeUtils.importESModule( const { sinon } = ChromeUtils.importESModule(
"resource://testing-common/Sinon.sys.mjs" "resource://testing-common/Sinon.sys.mjs"
); );
@ -129,54 +126,6 @@ add_task(async function test_initFeed_on_init() {
sandbox.restore(); sandbox.restore();
}); });
add_task(async function test_initFeed_calls__initIndexedDB() {
info("Store should call _initIndexedDB");
let sandbox = sinon.createSandbox();
let store = new Store();
sandbox.spy(store, "_initIndexedDB");
let dbStub = sandbox.stub(ASRouterStorage.prototype, "db");
let dbAccessed = false;
dbStub.get(() => {
dbAccessed = true;
return {};
});
store._prefs.set("testfeed", true);
await store.init(
new Map([
[
"testfeed",
() => {
return {};
},
],
])
);
Assert.ok(store._initIndexedDB.calledOnce, "_initIndexedDB called once");
Assert.ok(
store._initIndexedDB.calledWithExactly("feeds.telemetry"),
"feeds.telemetry was passed"
);
// Due to what appears to be a bug in sinon when using calledOnce
// with a stubbed getter, we can't just use dbStub.calledOnce here.
Assert.ok(dbAccessed, "ASRouterStorage was accessed");
info("Store should reset ASRouterStorage telemetry if opening the db fails");
dbStub.rejects();
await store.init(new Map());
Assert.equal(
store.dbStorage.telemetry,
null,
"Telemetry on storage was cleared"
);
sandbox.restore();
});
add_task(async function test_disabled_feed() { add_task(async function test_disabled_feed() {
info("Store should not initialize the feed if the Pref is set to false"); info("Store should not initialize the feed if the Pref is set to false");

View file

@ -13,7 +13,7 @@ const { actionCreators: ac, actionTypes: at } = ChromeUtils.importESModule(
); );
ChromeUtils.defineESModuleGetters(this, { ChromeUtils.defineESModuleGetters(this, {
FilterAdult: "resource://activity-stream/lib/FilterAdult.sys.mjs", FilterAdult: "resource:///modules/FilterAdult.sys.mjs",
NewTabUtils: "resource://gre/modules/NewTabUtils.sys.mjs", NewTabUtils: "resource://gre/modules/NewTabUtils.sys.mjs",
NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs", NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs",
PageThumbs: "resource://gre/modules/PageThumbs.sys.mjs", PageThumbs: "resource://gre/modules/PageThumbs.sys.mjs",
@ -73,14 +73,7 @@ function getTopSitesFeedForTest(sandbox) {
}); });
let feed = new TopSitesFeed(); let feed = new TopSitesFeed();
const storage = {
init: sandbox.stub().resolves(),
get: sandbox.stub().resolves(),
set: sandbox.stub().resolves(),
};
// Setup for tests that don't call `init` but require feed.storage
feed._storage = storage;
feed.store = { feed.store = {
dispatch: sinon.spy(), dispatch: sinon.spy(),
getState() { getState() {
@ -90,7 +83,6 @@ function getTopSitesFeedForTest(sandbox) {
Prefs: { values: { topSitesRows: 2 } }, Prefs: { values: { topSitesRows: 2 } },
TopSites: { rows: Array(12).fill("site") }, TopSites: { rows: Array(12).fill("site") },
}, },
dbStorage: { getDbTable: sandbox.stub().returns(storage) },
}; };
return feed; return feed;
@ -1026,13 +1018,6 @@ add_task(async function test_init() {
}) })
); );
info("TopSitesFeed.init should initialise the storage");
Assert.ok(
feed.store.dbStorage.getDbTable.calledOnce,
"getDbTable called once"
);
Assert.ok(feed.store.dbStorage.getDbTable.calledWithExactly("sectionPrefs"));
info( info(
"TopSitesFeed.init should call onUpdate to set up Nimbus update listener" "TopSitesFeed.init should call onUpdate to set up Nimbus update listener"
); );
@ -1089,7 +1074,7 @@ add_task(async function test_refresh() {
feed.store.dispatch.calledWithExactly( feed.store.dispatch.calledWithExactly(
ac.BroadcastToContent({ ac.BroadcastToContent({
type: at.TOP_SITES_UPDATED, type: at.TOP_SITES_UPDATED,
data: { links: [], pref: { collapsed: false } }, data: { links: [] },
}) })
) )
); );
@ -1179,7 +1164,7 @@ add_task(async function test_refresh_to_preloaded() {
feed.store.dispatch.calledWithExactly( feed.store.dispatch.calledWithExactly(
ac.AlsoToPreloaded({ ac.AlsoToPreloaded({
type: at.TOP_SITES_UPDATED, type: at.TOP_SITES_UPDATED,
data: { links: [], pref: { collapsed: false } }, data: { links: [] },
}) })
) )
); );
@ -1187,25 +1172,6 @@ add_task(async function test_refresh_to_preloaded() {
sandbox.restore(); sandbox.restore();
}); });
add_task(async function test_refresh_init_storage() {
let sandbox = sinon.createSandbox();
info(
"TopSitesFeed.refresh should not init storage of it's already initialized"
);
let feed = getTopSitesFeedForTest(sandbox);
sandbox.stub(feed, "_fetchIcon");
feed._startedUp = true;
feed._storage.initialized = true;
await feed.refresh({ broadcast: false });
Assert.ok(feed._storage.init.notCalled, "feed._storage.init was not called.");
sandbox.restore();
});
add_task(async function test_refresh_handles_indexedDB_errors() { add_task(async function test_refresh_handles_indexedDB_errors() {
let sandbox = sinon.createSandbox(); let sandbox = sinon.createSandbox();
@ -1217,8 +1183,6 @@ add_task(async function test_refresh_handles_indexedDB_errors() {
sandbox.stub(feed, "_fetchIcon"); sandbox.stub(feed, "_fetchIcon");
feed._startedUp = true; feed._startedUp = true;
feed._storage.get.throws(new Error());
try { try {
await feed.refresh({ broadcast: false }); await feed.refresh({ broadcast: false });
Assert.ok(true, "refresh should have succeeded"); Assert.ok(true, "refresh should have succeeded");
@ -1229,51 +1193,6 @@ add_task(async function test_refresh_handles_indexedDB_errors() {
sandbox.restore(); sandbox.restore();
}); });
add_task(async function test_updateSectionPrefs_on_UPDATE_SECTION_PREFS() {
let sandbox = sinon.createSandbox();
info(
"TopSitesFeed.onAction should call updateSectionPrefs on UPDATE_SECTION_PREFS"
);
let feed = getTopSitesFeedForTest(sandbox);
sandbox.stub(feed, "updateSectionPrefs");
feed.onAction({
type: at.UPDATE_SECTION_PREFS,
data: { id: "topsites" },
});
Assert.ok(
feed.updateSectionPrefs.calledOnce,
"feed.updateSectionPrefs called once"
);
sandbox.restore();
});
add_task(
async function test_updateSectionPrefs_dispatch_TOP_SITES_PREFS_UPDATED() {
let sandbox = sinon.createSandbox();
info(
"TopSitesFeed.updateSectionPrefs should dispatch TOP_SITES_PREFS_UPDATED"
);
let feed = getTopSitesFeedForTest(sandbox);
await feed.updateSectionPrefs({ collapsed: true });
Assert.ok(
feed.store.dispatch.calledWithExactly(
ac.BroadcastToContent({
type: at.TOP_SITES_PREFS_UPDATED,
data: { pref: { collapsed: true } },
})
)
);
sandbox.restore();
}
);
add_task(async function test_allocatePositions() { add_task(async function test_allocatePositions() {
let sandbox = sinon.createSandbox(); let sandbox = sinon.createSandbox();

View file

@ -5,7 +5,7 @@
const lazy = {}; const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, { ChromeUtils.defineESModuleGetters(lazy, {
FilterAdult: "resource://activity-stream/lib/FilterAdult.sys.mjs", FilterAdult: "resource:///modules/FilterAdult.sys.mjs",
UrlbarUtils: "resource:///modules/UrlbarUtils.sys.mjs", UrlbarUtils: "resource:///modules/UrlbarUtils.sys.mjs",
}); });

View file

@ -9,7 +9,7 @@ const ALLOWED_TEST_URL = "http://mochi.test:8888/";
const BLOCKED_TEST_URL = "https://example.com/browser"; const BLOCKED_TEST_URL = "https://example.com/browser";
ChromeUtils.defineESModuleGetters(this, { ChromeUtils.defineESModuleGetters(this, {
FilterAdult: "resource://activity-stream/lib/FilterAdult.sys.mjs", FilterAdult: "resource:///modules/FilterAdult.sys.mjs",
InteractionsBlocklist: "resource:///modules/InteractionsBlocklist.sys.mjs", InteractionsBlocklist: "resource:///modules/InteractionsBlocklist.sys.mjs",
}); });

View file

@ -75,8 +75,6 @@ support-files = ["trendingSuggestionEngine.sjs"]
["browser_search_discovery.js"] ["browser_search_discovery.js"]
["browser_search_nimbus_reload.js"]
["browser_searchbar_addEngine.js"] ["browser_searchbar_addEngine.js"]
["browser_searchbar_context.js"] ["browser_searchbar_context.js"]

View file

@ -1,55 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { ExperimentFakes } = ChromeUtils.importESModule(
"resource://testing-common/NimbusTestUtils.sys.mjs"
);
const { SearchService } = ChromeUtils.importESModule(
"resource://gre/modules/SearchService.sys.mjs"
);
const { sinon } = ChromeUtils.importESModule(
"resource://testing-common/Sinon.sys.mjs"
);
add_task(async function test_engines_reloaded_nimbus() {
let reloadSpy = sinon.spy(SearchService.prototype, "_maybeReloadEngines");
let getVariableSpy = sinon.spy(
NimbusFeatures.searchConfiguration,
"getVariable"
);
let doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({
featureId: "searchConfiguration",
value: { experiment: "nimbus-search-mochitest" },
});
Assert.equal(reloadSpy.callCount, 1, "Called by experiment enrollment");
await BrowserTestUtils.waitForCondition(
() => getVariableSpy.calledWith("experiment"),
"Wait for SearchService update to run"
);
Assert.equal(
getVariableSpy.callCount,
3,
"Called by update function to fetch engines"
);
Assert.ok(
getVariableSpy.calledWith("experiment"),
"Called by search service observer"
);
Assert.equal(
NimbusFeatures.searchConfiguration.getVariable("experiment"),
"nimbus-search-mochitest",
"Should have expected value"
);
doExperimentCleanup();
Assert.equal(reloadSpy.callCount, 2, "Called by experiment unenrollment");
reloadSpy.restore();
getVariableSpy.restore();
});

View file

@ -3,7 +3,7 @@ tags = "search-telemetry"
support-files = ["head.js", "head-spa.js"] support-files = ["head.js", "head-spa.js"]
prefs = ["browser.search.log=true"] prefs = ["browser.search.log=true"]
["browser_search_glean_serp_event_telemetry_categorization_enabled_by_nimbus_variable.js"] ["browser_search_glean_serp_event_telemetry_categorization_enabled_by_pref.js"]
support-files = ["searchTelemetryDomainCategorizationReporting.html"] support-files = ["searchTelemetryDomainCategorizationReporting.html"]
["browser_search_telemetry_abandonment.js"] ["browser_search_telemetry_abandonment.js"]

View file

@ -9,8 +9,6 @@ const TELEMETRY_PREF =
"browser.search.serpEventTelemetryCategorization.enabled"; "browser.search.serpEventTelemetryCategorization.enabled";
ChromeUtils.defineESModuleGetters(lazy, { ChromeUtils.defineESModuleGetters(lazy, {
ExperimentAPI: "resource://nimbus/ExperimentAPI.sys.mjs",
ExperimentFakes: "resource://testing-common/NimbusTestUtils.sys.mjs",
SearchSERPDomainToCategoriesMap: SearchSERPDomainToCategoriesMap:
"resource:///modules/SearchSERPTelemetry.sys.mjs", "resource:///modules/SearchSERPTelemetry.sys.mjs",
}); });
@ -96,10 +94,8 @@ add_task(async function test_enable_experiment_when_pref_is_not_enabled() {
let originalPrefValue = prefBranch.getBoolPref(TELEMETRY_PREF); let originalPrefValue = prefBranch.getBoolPref(TELEMETRY_PREF);
// Ensure the build being tested has the preference value as false. // Ensure the build being tested has the preference value as false.
// Changing the preference in the test must be done on the default branch // We do this on the default branch to simulate the value of the preference
// because in the telemetry code, we're referencing the preference directly // being changed by the user.
// instead of through NimbusFeatures. Enrolling in an experiment will change
// the default branch, and not overwrite the user branch.
prefBranch.setBoolPref(TELEMETRY_PREF, false); prefBranch.setBoolPref(TELEMETRY_PREF, false);
// If it was true, we should wait until the map is fully un-inited. // If it was true, we should wait until the map is fully un-inited.
@ -110,28 +106,18 @@ add_task(async function test_enable_experiment_when_pref_is_not_enabled() {
Assert.equal( Assert.equal(
lazy.serpEventsCategorizationEnabled, lazy.serpEventsCategorizationEnabled,
false, false,
"serpEventsCategorizationEnabled should be false when not enrolled in experiment and the default value is false." "serpEventsCategorizationEnabled should be false when the default value is false."
); );
await lazy.ExperimentAPI.ready(); info("Turn pref on");
info("Enroll in experiment.");
let updateComplete = waitForDomainToCategoriesUpdate(); let updateComplete = waitForDomainToCategoriesUpdate();
let doExperimentCleanup = await lazy.ExperimentFakes.enrollWithFeatureConfig( Services.prefs.setBoolPref(TELEMETRY_PREF, true);
{
featureId: NimbusFeatures.search.featureId,
value: {
serpEventTelemetryCategorizationEnabled: true,
},
},
{ isRollout: true }
);
Assert.equal( Assert.equal(
lazy.serpEventsCategorizationEnabled, lazy.serpEventsCategorizationEnabled,
true, true,
"serpEventsCategorizationEnabled should be true when enrolled in experiment." "serpEventsCategorizationEnabled should be true when the pref is true."
); );
await updateComplete; await updateComplete;
@ -169,14 +155,14 @@ add_task(async function test_enable_experiment_when_pref_is_not_enabled() {
]); ]);
resetTelemetry(); resetTelemetry();
info("End experiment."); info("Turn pref off");
doExperimentCleanup(); Services.prefs.setBoolPref(TELEMETRY_PREF, false);
await waitForDomainToCategoriesUninit(); await waitForDomainToCategoriesUninit();
Assert.equal( Assert.equal(
lazy.serpEventsCategorizationEnabled, lazy.serpEventsCategorizationEnabled,
false, false,
"serpEventsCategorizationEnabled should be false after experiment." "serpEventsCategorizationEnabled should be false when the pref is false."
); );
Assert.ok( Assert.ok(

View file

@ -185,9 +185,24 @@ export var RecentlyClosedTabsAndWindowsMenuUtils = {
? lazy.SessionStore.getWindows(currentWindow) ? lazy.SessionStore.getWindows(currentWindow)
: [currentWindow]; : [currentWindow];
for (const sourceWindow of browserWindows) { for (const sourceWindow of browserWindows) {
let count = lazy.SessionStore.getClosedTabCountForWindow(sourceWindow); let tabData = lazy.SessionStore.getClosedTabDataForWindow(sourceWindow);
while (--count >= 0) { let closedTabGroupsById = getClosedTabGroupsById();
lazy.SessionStore.undoCloseTab(sourceWindow, 0, currentWindow);
while (tabData.length) {
let currentTabGroupId = tabData[0].state.groupId;
if (currentTabGroupId && closedTabGroupsById.has(currentTabGroupId)) {
let currentTabGroup = closedTabGroupsById.get(currentTabGroupId);
tabData.splice(0, currentTabGroup.tabs.length);
lazy.SessionStore.undoCloseTabGroup(
sourceWindow,
currentTabGroupId,
currentWindow
);
} else {
tabData.splice(0, 1);
lazy.SessionStore.undoCloseTab(sourceWindow, 0, currentWindow);
}
} }
} }
if (lazy.closedTabsFromClosedWindowsEnabled) { if (lazy.closedTabsFromClosedWindowsEnabled) {

View file

@ -37,6 +37,13 @@ add_task(async function test_toggle_collapse_close_button() {
); );
is(computedStyle.opacity, "1", "The active tab is showing the close button."); is(computedStyle.opacity, "1", "The active tab is showing the close button.");
// Move mouse away from tabstrip to ensure we don't show the close button.
EventUtils.synthesizeMouseAtCenter(
document.getElementById("tabbrowser-tabbox"),
{ type: "mouseover" }
);
await TestUtils.waitForTick();
computedStyle = window.getComputedStyle( computedStyle = window.getComputedStyle(
firstTab.querySelector(".tab-close-button") firstTab.querySelector(".tab-close-button")
); );

View file

@ -49,6 +49,7 @@
this.addEventListener("mouseup", this); this.addEventListener("mouseup", this);
this.addEventListener("click", this); this.addEventListener("click", this);
this.addEventListener("dblclick", this, true); this.addEventListener("dblclick", this, true);
this.addEventListener("animationstart", this);
this.addEventListener("animationend", this); this.addEventListener("animationend", this);
this.addEventListener("focus", this); this.addEventListener("focus", this);
this.addEventListener("AriaFocus", this); this.addEventListener("AriaFocus", this);
@ -570,6 +571,21 @@
} }
} }
on_animationstart(event) {
if (!event.animationName.startsWith("tab-throbber-animation")) {
return;
}
// The animation is on a pseudo-element so we need to use `subtree: true`
// to get our hands on it.
for (let animation of event.target.getAnimations({ subtree: true })) {
if (animation.animationName === event.animationName) {
// Ensure all tab throbber animations are synchronized by sharing an
// start time.
animation.startTime = 0;
}
}
}
on_animationend(event) { on_animationend(event) {
if (event.target.classList.contains("tab-loading-burst")) { if (event.target.classList.contains("tab-loading-burst")) {
this.removeAttribute("bursting"); this.removeAttribute("bursting");

View file

@ -855,50 +855,6 @@
} }
} }
syncThrobberAnimations(aTab) {
aTab.ownerGlobal.promiseDocumentFlushed(() => {
if (!aTab.container) {
return;
}
const animations = Array.from(
aTab.container.getElementsByTagName("tab")
)
.filter(tab => tab.hasAttribute("busy"))
.flatMap(tab => tab.throbber?.getAnimations({ subtree: true }) ?? [])
.filter(
anim =>
CSSAnimation.isInstance(anim) &&
(anim.animationName === "tab-throbber-animation" ||
anim.animationName === "tab-throbber-animation-rtl") &&
anim.playState === "running"
);
// Synchronize with the oldest running animation, if any.
const firstStartTime = Math.min(
...animations.map(anim =>
anim.startTime === null ? Infinity : anim.startTime
)
);
if (firstStartTime === Infinity) {
return;
}
requestAnimationFrame(() => {
for (let animation of animations) {
// If |animation| has been cancelled since this rAF callback
// was scheduled we don't want to set its startTime since
// that would restart it. We check for a cancelled animation
// by looking for a null currentTime rather than checking
// the playState, since reading the playState of
// a CSSAnimation object will flush style.
if (animation.currentTime !== null) {
animation.startTime = firstStartTime;
}
}
});
});
}
getBrowserAtIndex(aIndex) { getBrowserAtIndex(aIndex) {
return this.browsers[aIndex]; return this.browsers[aIndex];
} }
@ -7454,7 +7410,6 @@
this.mTab.setAttribute("busy", "true"); this.mTab.setAttribute("busy", "true");
gBrowser._tabAttrModified(this.mTab, ["busy"]); gBrowser._tabAttrModified(this.mTab, ["busy"]);
this.mTab._notselectedsinceload = !this.mTab.selected; this.mTab._notselectedsinceload = !this.mTab.selected;
gBrowser.syncThrobberAnimations(this.mTab);
} }
if (this.mTab.selected) { if (this.mTab.selected) {

View file

@ -1121,8 +1121,6 @@
dropIndex++; dropIndex++;
} }
} }
gBrowser.syncThrobberAnimations(tab);
}; };
if (gReduceMotion) { if (gReduceMotion) {
postTransitionCleanup(); postTransitionCleanup();

View file

@ -116,6 +116,7 @@ add_task(async function test_allTabsView() {
*/ */
async function getContextMenu(triggerNode, contextMenuId) { async function getContextMenu(triggerNode, contextMenuId) {
let win = triggerNode.ownerGlobal; let win = triggerNode.ownerGlobal;
triggerNode.scrollIntoView();
const contextMenu = win.document.getElementById(contextMenuId); const contextMenu = win.document.getElementById(contextMenuId);
Assert.equal(contextMenu.state, "closed", "context menu is initially closed"); Assert.equal(contextMenu.state, "closed", "context menu is initially closed");
const contextMenuShown = BrowserTestUtils.waitForPopupEvent( const contextMenuShown = BrowserTestUtils.waitForPopupEvent(

View file

@ -23,7 +23,7 @@ const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, { ChromeUtils.defineESModuleGetters(lazy, {
FaviconFeed: "resource://activity-stream/lib/FaviconFeed.sys.mjs", FaviconFeed: "resource://activity-stream/lib/FaviconFeed.sys.mjs",
FilterAdult: "resource://activity-stream/lib/FilterAdult.sys.mjs", FilterAdult: "resource:///modules/FilterAdult.sys.mjs",
LinksCache: "resource://activity-stream/lib/LinksCache.sys.mjs", LinksCache: "resource://activity-stream/lib/LinksCache.sys.mjs",
NewTabUtils: "resource://gre/modules/NewTabUtils.sys.mjs", NewTabUtils: "resource://gre/modules/NewTabUtils.sys.mjs",
PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs", PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",

View file

@ -12,7 +12,7 @@ const { actionTypes: at } = ChromeUtils.importESModule(
); );
ChromeUtils.defineESModuleGetters(this, { ChromeUtils.defineESModuleGetters(this, {
FilterAdult: "resource://activity-stream/lib/FilterAdult.sys.mjs", FilterAdult: "resource:///modules/FilterAdult.sys.mjs",
NewTabUtils: "resource://gre/modules/NewTabUtils.sys.mjs", NewTabUtils: "resource://gre/modules/NewTabUtils.sys.mjs",
NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs", NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs",
shortURL: "resource://activity-stream/lib/ShortURL.sys.mjs", shortURL: "resource://activity-stream/lib/ShortURL.sys.mjs",

View file

@ -115,6 +115,7 @@ urlbar:
`merino_amo`, `merino_amo`,
`merino_top_picks`, `merino_top_picks`,
`merino_wikipedia`, `merino_wikipedia`,
`ml_yelp`,
`recent_search`, `recent_search`,
`remote_tab`, `remote_tab`,
`restrict_keyword_actions`, `restrict_keyword_actions`,
@ -261,6 +262,7 @@ urlbar:
`merino_amo`, `merino_amo`,
`merino_top_picks`, `merino_top_picks`,
`merino_wikipedia`, `merino_wikipedia`,
`ml_yelp`,
`recent_search`, `recent_search`,
`remote_tab`, `remote_tab`,
`restrict_keyword_actions`, `restrict_keyword_actions`,
@ -381,6 +383,7 @@ urlbar:
`merino_amo`, `merino_amo`,
`merino_top_picks`, `merino_top_picks`,
`merino_wikipedia`, `merino_wikipedia`,
`ml_yelp`,
`recent_search`, `recent_search`,
`remote_tab`, `remote_tab`,
`restrict_keyword_actions`, `restrict_keyword_actions`,

View file

@ -30,16 +30,12 @@ const RESULT_MENU_COMMAND = {
* A feature that supports Addon suggestions. * A feature that supports Addon suggestions.
*/ */
export class AddonSuggestions extends SuggestProvider { export class AddonSuggestions extends SuggestProvider {
get shouldEnable() {
return (
lazy.UrlbarPrefs.get("addonsFeatureGate") &&
lazy.UrlbarPrefs.get("suggest.addons") &&
lazy.UrlbarPrefs.get("suggest.quicksuggest.nonsponsored")
);
}
get enablingPreferences() { get enablingPreferences() {
return ["suggest.addons", "suggest.quicksuggest.nonsponsored"]; return [
"addonsFeatureGate",
"suggest.addons",
"suggest.quicksuggest.nonsponsored",
];
} }
get merinoProvider() { get merinoProvider() {

View file

@ -31,10 +31,6 @@ ChromeUtils.defineLazyGetter(lazy, "contextId", () => {
* A feature that manages AMP suggestions. * A feature that manages AMP suggestions.
*/ */
export class AmpSuggestions extends SuggestProvider { export class AmpSuggestions extends SuggestProvider {
get shouldEnable() {
return lazy.UrlbarPrefs.get("suggest.quicksuggest.sponsored");
}
get enablingPreferences() { get enablingPreferences() {
return ["suggest.quicksuggest.sponsored"]; return ["suggest.quicksuggest.sponsored"];
} }

View file

@ -12,7 +12,8 @@ ChromeUtils.defineESModuleGetters(lazy, {
}); });
/** /**
* A set of blocked suggestions for quick suggest. * A set of blocked suggestion URLs for Suggest. This feature is always enabled
* as long as Suggest is enabled.
*/ */
export class BlockedSuggestions extends SuggestFeature { export class BlockedSuggestions extends SuggestFeature {
constructor() { constructor() {
@ -21,14 +22,6 @@ export class BlockedSuggestions extends SuggestFeature {
lazy.UrlbarPrefs.addObserver(this); lazy.UrlbarPrefs.addObserver(this);
} }
get shouldEnable() {
// Return true so that we'll always load blocked digests when quick suggest
// is enabled, even if blocking new suggestions is currently disabled.
// Blocking may have been enabled previously, and blocked suggestions should
// remain blocked as long as quick suggest as a whole remains enabled.
return true;
}
enable(enabled) { enable(enabled) {
if (enabled) { if (enabled) {
this.#loadDigests(); this.#loadDigests();

View file

@ -16,14 +16,14 @@ ChromeUtils.defineESModuleGetters(lazy, {
* A feature for exposure suggestions. * A feature for exposure suggestions.
*/ */
export class ExposureSuggestions extends SuggestProvider { export class ExposureSuggestions extends SuggestProvider {
get shouldEnable() {
return !!this.exposureSuggestionTypes.size;
}
get enablingPreferences() { get enablingPreferences() {
return ["quicksuggest.exposureSuggestionTypes"]; return ["quicksuggest.exposureSuggestionTypes"];
} }
get additionalEnablingPredicate() {
return !!this.exposureSuggestionTypes.size;
}
get rustSuggestionType() { get rustSuggestionType() {
return "Exposure"; return "Exposure";
} }

View file

@ -84,16 +84,12 @@ export class FakespotSuggestions extends SuggestProvider {
lazy.UrlbarView.addDynamicViewTemplate("fakespot", VIEW_TEMPLATE); lazy.UrlbarView.addDynamicViewTemplate("fakespot", VIEW_TEMPLATE);
} }
get shouldEnable() {
return (
lazy.UrlbarPrefs.get("suggest.quicksuggest.sponsored") &&
lazy.UrlbarPrefs.get("fakespotFeatureGate") &&
lazy.UrlbarPrefs.get("suggest.fakespot")
);
}
get enablingPreferences() { get enablingPreferences() {
return ["suggest.quicksuggest.sponsored", "suggest.fakespot"]; return [
"fakespotFeatureGate",
"suggest.fakespot",
"suggest.quicksuggest.sponsored",
];
} }
get rustSuggestionType() { get rustSuggestionType() {

View file

@ -25,11 +25,11 @@ export class ImpressionCaps extends SuggestFeature {
lazy.UrlbarPrefs.addObserver(this); lazy.UrlbarPrefs.addObserver(this);
} }
get shouldEnable() { get enablingPreferences() {
return ( return [
lazy.UrlbarPrefs.get("quickSuggestImpressionCapsSponsoredEnabled") || "quickSuggestImpressionCapsSponsoredEnabled",
lazy.UrlbarPrefs.get("quickSuggestImpressionCapsNonSponsoredEnabled") "quickSuggestImpressionCapsNonSponsoredEnabled",
); ];
} }
enable(enabled) { enable(enabled) {

View file

@ -23,14 +23,6 @@ const RESULT_MENU_COMMAND = {
* A feature that supports MDN suggestions. * A feature that supports MDN suggestions.
*/ */
export class MDNSuggestions extends SuggestProvider { export class MDNSuggestions extends SuggestProvider {
get shouldEnable() {
return (
lazy.UrlbarPrefs.get("mdn.featureGate") &&
lazy.UrlbarPrefs.get("suggest.mdn") &&
lazy.UrlbarPrefs.get("suggest.quicksuggest.nonsponsored")
);
}
get enablingPreferences() { get enablingPreferences() {
return [ return [
"mdn.featureGate", "mdn.featureGate",

View file

@ -8,7 +8,6 @@ const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, { ChromeUtils.defineESModuleGetters(lazy, {
QuickSuggest: "resource:///modules/QuickSuggest.sys.mjs", QuickSuggest: "resource:///modules/QuickSuggest.sys.mjs",
UrlbarPrefs: "resource:///modules/UrlbarPrefs.sys.mjs",
UrlbarResult: "resource:///modules/UrlbarResult.sys.mjs", UrlbarResult: "resource:///modules/UrlbarResult.sys.mjs",
UrlbarUtils: "resource:///modules/UrlbarUtils.sys.mjs", UrlbarUtils: "resource:///modules/UrlbarUtils.sys.mjs",
}); });
@ -19,10 +18,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
* Instead they're handled directly by `UrlbarProviderQuickSuggest`. * Instead they're handled directly by `UrlbarProviderQuickSuggest`.
*/ */
export class OfflineWikipediaSuggestions extends SuggestProvider { export class OfflineWikipediaSuggestions extends SuggestProvider {
get shouldEnable() {
return lazy.UrlbarPrefs.get("suggest.quicksuggest.nonsponsored");
}
get enablingPreferences() { get enablingPreferences() {
return ["suggest.quicksuggest.nonsponsored"]; return ["suggest.quicksuggest.nonsponsored"];
} }

View file

@ -24,16 +24,12 @@ const RESULT_MENU_COMMAND = {
* A feature that manages Pocket suggestions in remote settings. * A feature that manages Pocket suggestions in remote settings.
*/ */
export class PocketSuggestions extends SuggestProvider { export class PocketSuggestions extends SuggestProvider {
get shouldEnable() {
return (
lazy.UrlbarPrefs.get("pocketFeatureGate") &&
lazy.UrlbarPrefs.get("suggest.pocket") &&
lazy.UrlbarPrefs.get("suggest.quicksuggest.nonsponsored")
);
}
get enablingPreferences() { get enablingPreferences() {
return ["suggest.pocket", "suggest.quicksuggest.nonsponsored"]; return [
"pocketFeatureGate",
"suggest.pocket",
"suggest.quicksuggest.nonsponsored",
];
} }
get merinoProvider() { get merinoProvider() {

View file

@ -16,10 +16,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
* Merino, also called "online" Suggest. * Merino, also called "online" Suggest.
*/ */
export class SuggestBackendMerino extends SuggestBackend { export class SuggestBackendMerino extends SuggestBackend {
get shouldEnable() {
return lazy.UrlbarPrefs.get("quicksuggest.dataCollection.enabled");
}
get enablingPreferences() { get enablingPreferences() {
return ["quicksuggest.dataCollection.enabled"]; return ["quicksuggest.dataCollection.enabled"];
} }

View file

@ -9,7 +9,6 @@ const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, { ChromeUtils.defineESModuleGetters(lazy, {
MLSuggest: "resource:///modules/urlbar/private/MLSuggest.sys.mjs", MLSuggest: "resource:///modules/urlbar/private/MLSuggest.sys.mjs",
QuickSuggest: "resource:///modules/QuickSuggest.sys.mjs", QuickSuggest: "resource:///modules/QuickSuggest.sys.mjs",
UrlbarPrefs: "resource:///modules/UrlbarPrefs.sys.mjs",
}); });
/** /**
@ -18,15 +17,8 @@ ChromeUtils.defineESModuleGetters(lazy, {
* query. * query.
*/ */
export class SuggestBackendMl extends SuggestBackend { export class SuggestBackendMl extends SuggestBackend {
get shouldEnable() {
return (
lazy.UrlbarPrefs.get("quickSuggestMlEnabled") &&
lazy.UrlbarPrefs.get("browser.ml.enable")
);
}
get enablingPreferences() { get enablingPreferences() {
return ["browser.ml.enable"]; return ["quickSuggestMlEnabled", "browser.ml.enable"];
} }
async enable(enabled) { async enable(enabled) {

View file

@ -112,10 +112,6 @@ export class SuggestBackendRust extends SuggestBackend {
return ["quicksuggest.rustEnabled"]; return ["quicksuggest.rustEnabled"];
} }
get shouldEnable() {
return lazy.UrlbarPrefs.get("quicksuggest.rustEnabled");
}
/** /**
* @returns {object} * @returns {object}
* The global Suggest config from the Rust component as returned from * The global Suggest config from the Rust component as returned from

View file

@ -24,33 +24,45 @@ export class SuggestFeature {
// Methods designed for overriding below // Methods designed for overriding below
/** /**
* {boolean} * @returns {Array}
* Whether the feature should be enabled. Typically the subclass will check * If the feature is conditioned on any prefs or Nimbus variables, the
* the values of one or more Nimbus variables or preferences. `QuickSuggest` * subclass should override this getter and return their names in this array
* will access this getter only when Suggest is enabled. When Suggest is * so that `update()` and `enable()` can be called when they change. Names
* disabled, the feature will be disabled automatically. * should be recognized by `UrlbarPrefs`, i.e., pref names should be
* relative to the `browser.urlbar.` branch. For Nimbus variables with
* fallback prefs, include only the variable name.
*
* When Suggest determines whether the feature should be enabled, it will
* call `UrlbarPrefs.get()` on each name in this array and disable the
* feature if any are falsey. If any of the prefs or variables are not
* booleans, the subclass may also need to override
* `additionalEnablingPredicate` to perform additional checks on them.
*/ */
get shouldEnable() { get enablingPreferences() {
throw new Error("`shouldEnable` must be overridden"); return [];
} }
/** /**
* @returns {Array} * @returns {boolean}
* If the subclass's `shouldEnable` implementation depends on any prefs that * If the feature is conditioned on any predicate other than the prefs and
* are not fallbacks for Nimbus variables, the subclass should override this * Nimbus variables in `enablingPreferences`, the subclass should override
* getter and return their names in this array so that `update()` can be * this getter and return whether the feature should be enabled. It may also
* called when they change. Names should be recognized by `UrlbarPrefs`. It * need to override this getter if any of the prefs or variables in
* doesn't hurt to include prefs that are fallbacks for Nimbus variables, * `enablingPreferences` are not booleans so that it can perform additional
* it's just not necessary because `QuickSuggest` will update all features * checks on them. (The predicate does not need to check prefs and variables
* whenever a `urlbar` Nimbus variable or its fallback pref changes. * in `enablingPreferences` that are booleans.)
*
* This getter will be called only when Suggest is enabled and all prefs and
* variables in `enablingPreferences` are truthy.
*/ */
get enablingPreferences() { get additionalEnablingPredicate() {
return null; return true;
} }
/** /**
* This method should initialize or uninitialize any state related to the * This method should initialize or uninitialize any state related to the
* feature. * feature. It will only be called when the enabled status changes, i.e., when
* it goes from false to true or true to false.
* *
* @param {boolean} enabled * @param {boolean} enabled
* Whether the feature should be enabled or not. * Whether the feature should be enabled or not.
@ -59,6 +71,17 @@ export class SuggestFeature {
// Methods not designed for overriding below // Methods not designed for overriding below
/**
* @returns {boolean}
* Whether the feature should be enabled, assuming Suggest is enabled.
*/
get shouldEnable() {
return (
this.enablingPreferences.every(p => lazy.UrlbarPrefs.get(p)) &&
this.additionalEnablingPredicate
);
}
/** /**
* @returns {Logger} * @returns {Logger}
* The feature's logger. * The feature's logger.
@ -92,9 +115,7 @@ export class SuggestFeature {
/** /**
* Enables or disables the feature according to `shouldEnable` and whether * Enables or disables the feature according to `shouldEnable` and whether
* Suggest is enabled. If the feature's enabled status changes, `enable()` is * Suggest is enabled. If the feature's enabled status changes, `enable()` is
* called with the new status; otherwise `enable()` is not called. If the * called with the new status; otherwise `enable()` is not called.
* feature manages any Rust suggestion types that become enabled as a result,
* they will be ingested.
*/ */
update() { update() {
let enable = let enable =

View file

@ -149,16 +149,12 @@ export class WeatherSuggestions extends SuggestProvider {
); );
} }
get shouldEnable() {
return (
lazy.UrlbarPrefs.get("suggest.quicksuggest.sponsored") &&
lazy.UrlbarPrefs.get("weatherFeatureGate") &&
lazy.UrlbarPrefs.get("suggest.weather")
);
}
get enablingPreferences() { get enablingPreferences() {
return ["suggest.quicksuggest.sponsored", "suggest.weather"]; return [
"weatherFeatureGate",
"suggest.weather",
"suggest.quicksuggest.sponsored",
];
} }
get rustSuggestionType() { get rustSuggestionType() {

View file

@ -29,16 +29,12 @@ const RESULT_MENU_COMMAND = {
* A feature for Yelp suggestions. * A feature for Yelp suggestions.
*/ */
export class YelpSuggestions extends SuggestProvider { export class YelpSuggestions extends SuggestProvider {
get shouldEnable() {
return (
lazy.UrlbarPrefs.get("suggest.quicksuggest.sponsored") &&
lazy.UrlbarPrefs.get("yelpFeatureGate") &&
lazy.UrlbarPrefs.get("suggest.yelp")
);
}
get enablingPreferences() { get enablingPreferences() {
return ["suggest.quicksuggest.sponsored", "suggest.yelp"]; return [
"yelpFeatureGate",
"suggest.yelp",
"suggest.quicksuggest.sponsored",
];
} }
get rustSuggestionType() { get rustSuggestionType() {

View file

@ -630,29 +630,6 @@ add_task(async function nimbusScotchBonnetEnableOverride() {
}); });
}); });
add_task(async function nimbusLogEnabled() {
info("Setup initial local pref");
await SpecialPowers.pushPrefEnv({
set: [["browser.search.log", false]],
});
await TestUtils.waitForCondition(() => {
return !Services.prefs.getBoolPref("browser.search.log");
});
info("Setup Numbus value");
const cleanUpNimbusEnable = await UrlbarTestUtils.initNimbusFeature(
{ logEnabled: true },
"search"
);
await TestUtils.waitForCondition(() => {
return Services.prefs.getBoolPref("browser.search.log");
});
Assert.ok(true, "browser.search.log is changed properly");
await cleanUpNimbusEnable();
await SpecialPowers.popPrefEnv();
});
add_task(async function test_button_stuck() { add_task(async function test_button_stuck() {
let win = await BrowserTestUtils.openNewBrowserWindow(); let win = await BrowserTestUtils.openNewBrowserWindow();
let popup = win.document.getElementById("searchmode-switcher-popup"); let popup = win.document.getElementById("searchmode-switcher-popup");

View file

@ -18,6 +18,13 @@ preonboarding-privacy-notice-header-button-title = Read our Privacy Notice
# Label for header style button that toggles showing the data preference checklist # Label for header style button that toggles showing the data preference checklist
preonboarding-manage-data-header-button-title = Manage diagnostic and interaction data preonboarding-manage-data-header-button-title = Manage diagnostic and interaction data
# Label for header style button that toggles showing the Terms of Use (Variant B)
preonboarding-terms-of-use-header-button-title-b = { -brand-product-name } Terms of Use
# Label for header style button that toggles showing the Privacy Notice (Variant B)
preonboarding-privacy-notice-header-button-title-b = { -brand-product-name } Privacy Notice
# Description under label for header style buttons
preonboarding-header-button-description = Read More
# New user onboarding checklist # New user onboarding checklist
preonboarding-checklist-interaction-data-label = Send technical and interaction data to { -vendor-short-name } preonboarding-checklist-interaction-data-label = Send technical and interaction data to { -vendor-short-name }
preonboarding-checklist-interaction-data-description = Data about your device, hardware configuration, and how you use { -brand-product-name } helps improve features, performance, and stability for users everywhere. preonboarding-checklist-interaction-data-description = Data about your device, hardware configuration, and how you use { -brand-product-name } helps improve features, performance, and stability for users everywhere.

View file

@ -16,7 +16,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"af": { "af": {
"pin": false, "pin": false,
@ -35,7 +35,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"an": { "an": {
"pin": false, "pin": false,
@ -54,7 +54,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"ar": { "ar": {
"pin": false, "pin": false,
@ -73,7 +73,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"ast": { "ast": {
"pin": false, "pin": false,
@ -92,7 +92,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"az": { "az": {
"pin": false, "pin": false,
@ -111,7 +111,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"be": { "be": {
"pin": false, "pin": false,
@ -130,7 +130,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"bg": { "bg": {
"pin": false, "pin": false,
@ -149,7 +149,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"bn": { "bn": {
"pin": false, "pin": false,
@ -168,7 +168,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"bo": { "bo": {
"pin": false, "pin": false,
@ -187,7 +187,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"br": { "br": {
"pin": false, "pin": false,
@ -206,7 +206,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"brx": { "brx": {
"pin": false, "pin": false,
@ -225,7 +225,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"bs": { "bs": {
"pin": false, "pin": false,
@ -244,7 +244,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"ca": { "ca": {
"pin": false, "pin": false,
@ -263,7 +263,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"ca-valencia": { "ca-valencia": {
"pin": false, "pin": false,
@ -282,7 +282,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"cak": { "cak": {
"pin": false, "pin": false,
@ -301,7 +301,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"ckb": { "ckb": {
"pin": false, "pin": false,
@ -320,7 +320,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"cs": { "cs": {
"pin": false, "pin": false,
@ -339,7 +339,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"cy": { "cy": {
"pin": false, "pin": false,
@ -358,7 +358,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"da": { "da": {
"pin": false, "pin": false,
@ -377,7 +377,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"de": { "de": {
"pin": false, "pin": false,
@ -396,7 +396,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"dsb": { "dsb": {
"pin": false, "pin": false,
@ -415,7 +415,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"el": { "el": {
"pin": false, "pin": false,
@ -434,7 +434,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"en-CA": { "en-CA": {
"pin": false, "pin": false,
@ -453,7 +453,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"en-GB": { "en-GB": {
"pin": false, "pin": false,
@ -472,7 +472,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"eo": { "eo": {
"pin": false, "pin": false,
@ -491,7 +491,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"es-AR": { "es-AR": {
"pin": false, "pin": false,
@ -510,7 +510,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"es-CL": { "es-CL": {
"pin": false, "pin": false,
@ -529,7 +529,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"es-ES": { "es-ES": {
"pin": false, "pin": false,
@ -548,7 +548,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"es-MX": { "es-MX": {
"pin": false, "pin": false,
@ -567,7 +567,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"et": { "et": {
"pin": false, "pin": false,
@ -586,7 +586,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"eu": { "eu": {
"pin": false, "pin": false,
@ -605,7 +605,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"fa": { "fa": {
"pin": false, "pin": false,
@ -624,7 +624,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"ff": { "ff": {
"pin": false, "pin": false,
@ -643,7 +643,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"fi": { "fi": {
"pin": false, "pin": false,
@ -662,7 +662,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"fr": { "fr": {
"pin": false, "pin": false,
@ -681,7 +681,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"fur": { "fur": {
"pin": false, "pin": false,
@ -700,7 +700,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"fy-NL": { "fy-NL": {
"pin": false, "pin": false,
@ -719,7 +719,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"ga-IE": { "ga-IE": {
"pin": false, "pin": false,
@ -738,7 +738,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"gd": { "gd": {
"pin": false, "pin": false,
@ -757,7 +757,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"gl": { "gl": {
"pin": false, "pin": false,
@ -776,7 +776,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"gn": { "gn": {
"pin": false, "pin": false,
@ -795,7 +795,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"gu-IN": { "gu-IN": {
"pin": false, "pin": false,
@ -814,7 +814,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"he": { "he": {
"pin": false, "pin": false,
@ -833,7 +833,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"hi-IN": { "hi-IN": {
"pin": false, "pin": false,
@ -852,7 +852,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"hr": { "hr": {
"pin": false, "pin": false,
@ -871,7 +871,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"hsb": { "hsb": {
"pin": false, "pin": false,
@ -890,7 +890,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"hu": { "hu": {
"pin": false, "pin": false,
@ -909,7 +909,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"hy-AM": { "hy-AM": {
"pin": false, "pin": false,
@ -928,7 +928,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"hye": { "hye": {
"pin": false, "pin": false,
@ -947,7 +947,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"ia": { "ia": {
"pin": false, "pin": false,
@ -966,7 +966,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"id": { "id": {
"pin": false, "pin": false,
@ -985,7 +985,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"is": { "is": {
"pin": false, "pin": false,
@ -1004,7 +1004,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"it": { "it": {
"pin": false, "pin": false,
@ -1023,7 +1023,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"ja": { "ja": {
"pin": false, "pin": false,
@ -1040,7 +1040,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"ja-JP-mac": { "ja-JP-mac": {
"pin": false, "pin": false,
@ -1048,7 +1048,7 @@
"macosx64", "macosx64",
"macosx64-devedition" "macosx64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"ka": { "ka": {
"pin": false, "pin": false,
@ -1067,7 +1067,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"kab": { "kab": {
"pin": false, "pin": false,
@ -1086,7 +1086,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"kk": { "kk": {
"pin": false, "pin": false,
@ -1105,7 +1105,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"km": { "km": {
"pin": false, "pin": false,
@ -1124,7 +1124,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"kn": { "kn": {
"pin": false, "pin": false,
@ -1143,7 +1143,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"ko": { "ko": {
"pin": false, "pin": false,
@ -1162,7 +1162,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"lij": { "lij": {
"pin": false, "pin": false,
@ -1181,7 +1181,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"lo": { "lo": {
"pin": false, "pin": false,
@ -1200,7 +1200,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"lt": { "lt": {
"pin": false, "pin": false,
@ -1219,7 +1219,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"ltg": { "ltg": {
"pin": false, "pin": false,
@ -1238,7 +1238,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"lv": { "lv": {
"pin": false, "pin": false,
@ -1257,7 +1257,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"meh": { "meh": {
"pin": false, "pin": false,
@ -1276,7 +1276,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"mk": { "mk": {
"pin": false, "pin": false,
@ -1295,7 +1295,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"mr": { "mr": {
"pin": false, "pin": false,
@ -1314,7 +1314,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"ms": { "ms": {
"pin": false, "pin": false,
@ -1333,7 +1333,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"my": { "my": {
"pin": false, "pin": false,
@ -1352,7 +1352,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"nb-NO": { "nb-NO": {
"pin": false, "pin": false,
@ -1371,7 +1371,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"ne-NP": { "ne-NP": {
"pin": false, "pin": false,
@ -1390,7 +1390,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"nl": { "nl": {
"pin": false, "pin": false,
@ -1409,7 +1409,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"nn-NO": { "nn-NO": {
"pin": false, "pin": false,
@ -1428,7 +1428,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"oc": { "oc": {
"pin": false, "pin": false,
@ -1447,7 +1447,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"pa-IN": { "pa-IN": {
"pin": false, "pin": false,
@ -1466,7 +1466,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"pl": { "pl": {
"pin": false, "pin": false,
@ -1485,7 +1485,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"pt-BR": { "pt-BR": {
"pin": false, "pin": false,
@ -1504,7 +1504,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"pt-PT": { "pt-PT": {
"pin": false, "pin": false,
@ -1523,7 +1523,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"rm": { "rm": {
"pin": false, "pin": false,
@ -1542,7 +1542,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"ro": { "ro": {
"pin": false, "pin": false,
@ -1561,7 +1561,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"ru": { "ru": {
"pin": false, "pin": false,
@ -1580,7 +1580,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"sat": { "sat": {
"pin": false, "pin": false,
@ -1599,7 +1599,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"sc": { "sc": {
"pin": false, "pin": false,
@ -1618,7 +1618,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"scn": { "scn": {
"pin": false, "pin": false,
@ -1637,7 +1637,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"sco": { "sco": {
"pin": false, "pin": false,
@ -1656,7 +1656,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"si": { "si": {
"pin": false, "pin": false,
@ -1675,7 +1675,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"sk": { "sk": {
"pin": false, "pin": false,
@ -1694,7 +1694,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"skr": { "skr": {
"pin": false, "pin": false,
@ -1713,7 +1713,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"sl": { "sl": {
"pin": false, "pin": false,
@ -1732,7 +1732,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"son": { "son": {
"pin": false, "pin": false,
@ -1751,7 +1751,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"sq": { "sq": {
"pin": false, "pin": false,
@ -1770,7 +1770,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"sr": { "sr": {
"pin": false, "pin": false,
@ -1789,7 +1789,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"sv-SE": { "sv-SE": {
"pin": false, "pin": false,
@ -1808,7 +1808,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"szl": { "szl": {
"pin": false, "pin": false,
@ -1827,7 +1827,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"ta": { "ta": {
"pin": false, "pin": false,
@ -1846,7 +1846,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"te": { "te": {
"pin": false, "pin": false,
@ -1865,7 +1865,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"tg": { "tg": {
"pin": false, "pin": false,
@ -1884,7 +1884,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"th": { "th": {
"pin": false, "pin": false,
@ -1903,7 +1903,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"tl": { "tl": {
"pin": false, "pin": false,
@ -1922,7 +1922,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"tr": { "tr": {
"pin": false, "pin": false,
@ -1941,7 +1941,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"trs": { "trs": {
"pin": false, "pin": false,
@ -1960,7 +1960,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"uk": { "uk": {
"pin": false, "pin": false,
@ -1979,7 +1979,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"ur": { "ur": {
"pin": false, "pin": false,
@ -1998,7 +1998,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"uz": { "uz": {
"pin": false, "pin": false,
@ -2017,7 +2017,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"vi": { "vi": {
"pin": false, "pin": false,
@ -2036,7 +2036,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"wo": { "wo": {
"pin": false, "pin": false,
@ -2055,7 +2055,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"xh": { "xh": {
"pin": false, "pin": false,
@ -2074,7 +2074,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"zh-CN": { "zh-CN": {
"pin": false, "pin": false,
@ -2093,7 +2093,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
}, },
"zh-TW": { "zh-TW": {
"pin": false, "pin": false,
@ -2112,6 +2112,6 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "67e3e0da074da1a66f97aeb649d1469373e8b7cf" "revision": "1fc67833f6f1b3390afc9f2834527fb8648bc299"
} }
} }

View file

@ -2,16 +2,7 @@
* 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/. */
// We use importESModule here instead of static import so that import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
// the Karma test environment won't choke on this module. This
// is because the Karma test environment already stubs out
// XPCOMUtils, and overrides importESModule to be a no-op (which
// can't be done for a static import statement).
// eslint-disable-next-line mozilla/use-static-import
const { XPCOMUtils } = ChromeUtils.importESModule(
"resource://gre/modules/XPCOMUtils.sys.mjs"
);
const lazy = {}; const lazy = {};

View file

@ -123,6 +123,7 @@ EXTRA_JS_MODULES += [
"EveryWindow.sys.mjs", "EveryWindow.sys.mjs",
"ExtensionsUI.sys.mjs", "ExtensionsUI.sys.mjs",
"FaviconLoader.sys.mjs", "FaviconLoader.sys.mjs",
"FilterAdult.sys.mjs",
"FirefoxBridgeExtensionUtils.sys.mjs", "FirefoxBridgeExtensionUtils.sys.mjs",
"HomePage.sys.mjs", "HomePage.sys.mjs",
"LaterRun.sys.mjs", "LaterRun.sys.mjs",

View file

@ -0,0 +1,119 @@
/* Any copyright is dedicated to the Public Domain.
* https://creativecommons.org/publicdomain/zero/1.0/
*/
"use strict";
const { FilterAdult } = ChromeUtils.importESModule(
"resource:///modules/FilterAdult.sys.mjs"
);
let originalPrefValue;
const FILTER_ADULT_ENABLED_PREF =
"browser.newtabpage.activity-stream.filterAdult";
const TEST_ADULT_SITE_URL = "https://some-adult-site.com/";
add_setup(async function setup() {
// Save the original preference value to restore later
originalPrefValue = Services.prefs.getBoolPref(
FILTER_ADULT_ENABLED_PREF,
true
);
// Enable the filter preference for testing
Services.prefs.setBoolPref(FILTER_ADULT_ENABLED_PREF, true);
registerCleanupFunction(() => {
// Restore the original preference value after all tests
Services.prefs.setBoolPref(FILTER_ADULT_ENABLED_PREF, originalPrefValue);
});
});
add_task(async function test_defaults_to_include_unexpected_urls() {
const empty = {};
const result = FilterAdult.filter([empty]);
Assert.equal(result.length, 1);
Assert.equal(result[0], empty);
});
add_task(async function test_does_not_filter_non_adult_urls() {
const link = { url: "https://mozilla.org/" };
const result = FilterAdult.filter([link]);
Assert.equal(result.length, 1);
Assert.equal(result[0], link);
});
add_task(async function test_filters_out_adult_urls() {
// Add a domain to the adult list
FilterAdult.addDomainToList(TEST_ADULT_SITE_URL);
const link = { url: TEST_ADULT_SITE_URL };
const result = FilterAdult.filter([link]);
Assert.equal(result.length, 0);
// Clean up
FilterAdult.removeDomainFromList(TEST_ADULT_SITE_URL);
});
add_task(async function test_does_not_filter_adult_urls_when_pref_off() {
// Disable the filter preference
Services.prefs.setBoolPref(FILTER_ADULT_ENABLED_PREF, false);
// Add a domain to the adult list
FilterAdult.addDomainToList(TEST_ADULT_SITE_URL);
const link = { url: TEST_ADULT_SITE_URL };
const result = FilterAdult.filter([link]);
Assert.equal(result.length, 1);
Assert.equal(result[0], link);
// Re-enable the preference
Services.prefs.setBoolPref(FILTER_ADULT_ENABLED_PREF, true);
// Clean up
FilterAdult.removeDomainFromList(TEST_ADULT_SITE_URL);
});
add_task(async function test_isAdultUrl_returns_false_for_unexpected_urls() {
const result = FilterAdult.isAdultUrl("");
Assert.equal(result, false);
});
add_task(async function test_isAdultUrl_returns_false_for_non_adult_urls() {
const result = FilterAdult.isAdultUrl("https://mozilla.org/");
Assert.equal(result, false);
});
add_task(async function test_isAdultUrl_returns_true_for_adult_urls() {
// Add a domain to the adult list
FilterAdult.addDomainToList(TEST_ADULT_SITE_URL);
const result = FilterAdult.isAdultUrl(TEST_ADULT_SITE_URL);
Assert.equal(result, true);
// Clean up
FilterAdult.removeDomainFromList(TEST_ADULT_SITE_URL);
});
add_task(async function test_isAdultUrl_returns_false_when_pref_off() {
// Disable the filter preference
Services.prefs.setBoolPref(FILTER_ADULT_ENABLED_PREF, false);
// Add a domain to the adult list
FilterAdult.addDomainToList(TEST_ADULT_SITE_URL);
const result = FilterAdult.isAdultUrl(TEST_ADULT_SITE_URL);
Assert.equal(result, false);
// Re-enable the preference
Services.prefs.setBoolPref(FILTER_ADULT_ENABLED_PREF, true);
// Clean up
FilterAdult.removeDomainFromList(TEST_ADULT_SITE_URL);
});
add_task(async function test_add_and_remove_from_adult_list() {
// Add a domain to the adult list
FilterAdult.addDomainToList(TEST_ADULT_SITE_URL);
let result = FilterAdult.isAdultUrl(TEST_ADULT_SITE_URL);
Assert.equal(result, true);
// Remove the domain from the list
FilterAdult.removeDomainFromList(TEST_ADULT_SITE_URL);
result = FilterAdult.isAdultUrl(TEST_ADULT_SITE_URL);
Assert.equal(result, false);
});

View file

@ -6,6 +6,8 @@ tags = "os_integration"
["test_E10SUtils_nested_URIs.js"] ["test_E10SUtils_nested_URIs.js"]
["test_FilterAdult.js"]
["test_FirefoxBridgeExtensionUtils.js"] ["test_FirefoxBridgeExtensionUtils.js"]
run-if = ["os == 'win'"] # Test of a Windows-specific feature run-if = ["os == 'win'"] # Test of a Windows-specific feature

View file

@ -439,7 +439,7 @@ def assert_rust_compile(host_or_target, rustc_target, rustc):
suffix=".rlib" suffix=".rlib"
) as out_path: ) as out_path:
with open(in_path, "w") as fd: with open(in_path, "w") as fd:
source = b'pub extern fn hello() { println!("Hello world"); }' source = b'pub extern "C" fn hello() { println!("Hello world"); }'
log.debug("Creating `%s` with content:", in_path) log.debug("Creating `%s` with content:", in_path)
with LineIO(lambda l: log.debug("| %s", l)) as out: with LineIO(lambda l: log.debug("| %s", l)) as out:
out.write(source) out.write(source)

View file

@ -18,6 +18,10 @@ const {
const { const {
getFormattedTime, getFormattedTime,
} = require("resource://devtools/client/netmonitor/src/utils/format-utils.js"); } = require("resource://devtools/client/netmonitor/src/utils/format-utils.js");
const { truncateString } = require("resource://devtools/shared/string.js");
const {
MAX_UI_STRING_LENGTH,
} = require("resource://devtools/client/netmonitor/src/constants.js");
const UPDATED_FILE_PROPS = ["urlDetails", "waitingTime"]; const UPDATED_FILE_PROPS = ["urlDetails", "waitingTime"];
@ -66,9 +70,9 @@ module.exports = class RequestListColumnFile extends Component {
return dom.td( return dom.td(
{ {
className: "requests-list-column requests-list-file", className: "requests-list-column requests-list-file",
title: fileToolTip, title: truncateString(fileToolTip, MAX_UI_STRING_LENGTH),
}, },
dom.div({}, requestedFile), dom.div({}, truncateString(requestedFile, MAX_UI_STRING_LENGTH)),
isSlow && isSlow &&
dom.div({ dom.div({
title: L10N.getFormatStr( title: L10N.getFormatStr(

View file

@ -24,6 +24,11 @@ const {
const SecurityState = createFactory( const SecurityState = createFactory(
require("resource://devtools/client/netmonitor/src/components/SecurityState.js") require("resource://devtools/client/netmonitor/src/components/SecurityState.js")
); );
const { truncateString } = require("resource://devtools/shared/string.js");
const {
MAX_UI_STRING_LENGTH,
} = require("resource://devtools/client/netmonitor/src/constants.js");
const UPDATED_FILE_PROPS = ["remoteAddress", "securityState", "urlDetails"]; const UPDATED_FILE_PROPS = ["remoteAddress", "securityState", "urlDetails"];
class RequestListColumnUrl extends Component { class RequestListColumnUrl extends Component {
@ -78,10 +83,10 @@ class RequestListColumnUrl extends Component {
return td( return td(
{ {
className: "requests-list-column requests-list-url", className: "requests-list-column requests-list-url",
title: urlToolTip + title, title: truncateString(urlToolTip, MAX_UI_STRING_LENGTH) + title,
}, },
SecurityState({ item, onSecurityIconMouseDown, isLocal }), SecurityState({ item, onSecurityIconMouseDown, isLocal }),
originalURL truncateString(originalURL, MAX_UI_STRING_LENGTH)
); );
} }
} }

View file

@ -384,7 +384,16 @@ class RequestListContent extends Component {
}); });
} }
this.contextMenu.open(evt, clickedRequest, displayedRequests, blockedUrls); const filteredBlockedUrls = blockedUrls
.map(({ enabled, url }) => (enabled ? url : null))
.filter(Boolean);
this.contextMenu.open(
evt,
clickedRequest,
displayedRequests,
filteredBlockedUrls
);
} }
render() { render() {
@ -471,9 +480,7 @@ class RequestListContent extends Component {
module.exports = connect( module.exports = connect(
state => ({ state => ({
blockedUrls: state.requestBlocking.blockedUrls blockedUrls: state.requestBlocking.blockedUrls,
.map(({ enabled, url }) => (enabled ? url : null))
.filter(Boolean),
columns: getColumns(state), columns: getColumns(state),
networkActionOpen: state.ui.networkActionOpen, networkActionOpen: state.ui.networkActionOpen,
networkDetailsOpen: state.ui.networkDetailsOpen, networkDetailsOpen: state.ui.networkDetailsOpen,

View file

@ -610,6 +610,9 @@ const general = {
AUTO_EXPAND_MAX_NODES: 50, AUTO_EXPAND_MAX_NODES: 50,
CHANNEL_TYPE, CHANNEL_TYPE,
WEB_SOCKET_OPCODE, WEB_SOCKET_OPCODE,
// Arbitrary limit for rendering strings in the netmonitor table.
// Useful for instance for very big data URIs.
MAX_UI_STRING_LENGTH: 10000,
}; };
// flatten constants // flatten constants

View file

@ -44,44 +44,39 @@ function sortWithClones(requests, sorter, a, b) {
return sorter ? sorter(a, b) : defaultSorter; return sorter ? sorter(a, b) : defaultSorter;
} }
const getActiveFilters = createSelector(
state => state.filters.requestFilterTypes,
requestFilterTypes =>
Object.keys(requestFilterTypes)
.filter(type => requestFilterTypes[type] && Filters[type])
.map(type => Filters[type])
);
/** /**
* Take clones into account when filtering. If a request is * Take clones into account when filtering. If a request is
* a clone, it's not filtered out. * a clone, it's not filtered out.
*/ */
const getFilterWithCloneFn = createSelector( const getFilterWithCloneFn = createSelector(
state => state.filters, getActiveFilters,
filters => r => { state => state.filters.requestFilterText,
const matchesType = Object.keys(filters.requestFilterTypes).some(filter => { (activeFilters, requestFilterText) => {
if (r.id.endsWith("-clone")) { return r => {
return true; const isClone = r.id.endsWith("-clone");
} const matchesType = activeFilters.some(filter => filter(r));
return ( return (isClone || matchesType) && isFreetextMatch(r, requestFilterText);
filters.requestFilterTypes[filter] && };
Filters[filter] &&
Filters[filter](r)
);
});
return matchesType && isFreetextMatch(r, filters.requestFilterText);
} }
); );
const getTypeFilterFn = createSelector( const getTypeFilterFn = createSelector(
state => state.filters, getActiveFilters,
filters => r => { activeFilters => r => activeFilters.some(filter => filter(r))
return Object.keys(filters.requestFilterTypes).some(filter => {
return (
filters.requestFilterTypes[filter] &&
Filters[filter] &&
Filters[filter](r)
);
});
}
); );
const getSortFn = createSelector( const getSortFn = createSelector(
state => state.requests, state => state.requests.requests,
state => state.sort, state => state.sort,
({ requests }, sort) => { (requests, sort) => {
const sorter = Sorters[sort.type || "waterfall"]; const sorter = Sorters[sort.type || "waterfall"];
const ascending = sort.ascending ? +1 : -1; const ascending = sort.ascending ? +1 : -1;
return (a, b) => ascending * sortWithClones(requests, sorter, a, b); return (a, b) => ascending * sortWithClones(requests, sorter, a, b);
@ -89,22 +84,22 @@ const getSortFn = createSelector(
); );
const getSortedRequests = createSelector( const getSortedRequests = createSelector(
state => state.requests, state => state.requests.requests,
getSortFn, getSortFn,
({ requests }, sortFn) => [...requests].sort(sortFn) (requests, sortFn) => [...requests].sort(sortFn)
); );
const getDisplayedRequests = createSelector( const getDisplayedRequests = createSelector(
state => state.requests, state => state.requests.requests,
getFilterWithCloneFn, getFilterWithCloneFn,
getSortFn, getSortFn,
({ requests }, filterFn, sortFn) => requests.filter(filterFn).sort(sortFn) (requests, filterFn, sortFn) => requests.filter(filterFn).sort(sortFn)
); );
const getTypeFilteredRequests = createSelector( const getTypeFilteredRequests = createSelector(
state => state.requests, state => state.requests.requests,
getTypeFilterFn, getTypeFilterFn,
({ requests }, filterFn) => requests.filter(filterFn) (requests, filterFn) => requests.filter(filterFn)
); );
const getDisplayedRequestsSummary = createSelector( const getDisplayedRequestsSummary = createSelector(
@ -143,15 +138,16 @@ const getDisplayedRequestsSummary = createSelector(
); );
const getSelectedRequest = createSelector( const getSelectedRequest = createSelector(
state => state.requests, state => state.requests.requests,
({ selectedId, requests }) => state => state.requests.selectedId,
(requests, selectedId) =>
selectedId ? requests.find(item => item.id === selectedId) : undefined selectedId ? requests.find(item => item.id === selectedId) : undefined
); );
const isSelectedRequestVisible = createSelector( const isSelectedRequestVisible = createSelector(
state => state.requests, state => state.requests.selectedId,
getDisplayedRequests, getDisplayedRequests,
({ selectedId }, displayedRequests) => (selectedId, displayedRequests) =>
displayedRequests.some(r => r.id === selectedId) displayedRequests.some(r => r.id === selectedId)
); );
@ -178,8 +174,9 @@ function getRecordingState(state) {
} }
const getClickedRequest = createSelector( const getClickedRequest = createSelector(
state => state.requests, state => state.requests.requests,
({ requests, clickedRequestId }) => state => state.requests.clickedRequestId,
(requests, clickedRequestId) =>
requests.find(request => request.id == clickedRequestId) requests.find(request => request.id == clickedRequestId)
); );

View file

@ -53,23 +53,17 @@ function getVisibleColumns(columns) {
} }
const getColumns = createSelector( const getColumns = createSelector(
state => state.ui, state => state.ui.columns,
state => state.search, state => state.ui.networkDetailsOpen || state.search.panelOpen,
(ui, search) => { (columns, isSidePanelOpen) => {
if ( const isWaterfallOnly =
((ui.networkDetailsOpen || search.panelOpen) && getVisibleColumns(columns).length === 1 && columns.waterfall;
getVisibleColumns(ui.columns).length === 1 && if (isSidePanelOpen && !isWaterfallOnly) {
ui.columns.waterfall) || // Remove the Waterfall column if it is not the only column and a side
(!ui.networkDetailsOpen && !search.panelOpen) // panel is open.
) { columns = { ...columns };
return ui.columns; delete columns.waterfall;
} }
// Remove the Waterfall/Timeline column from the list of available
// columns if the details side-bar is opened and more than one column is
// visible.
const columns = { ...ui.columns };
delete columns.waterfall;
return columns; return columns;
} }
); );

View file

@ -48,7 +48,6 @@ function trimUrlQuery(url) {
// Map suffix to content type. // Map suffix to content type.
const contentMap = { const contentMap = {
js: "text/javascript", js: "text/javascript",
jsm: "text/javascript",
mjs: "text/javascript", mjs: "text/javascript",
ts: "text/typescript", ts: "text/typescript",
tsx: "text/typescript-jsx", tsx: "text/typescript-jsx",

View file

@ -32,10 +32,10 @@ frame-script
Defines the environment for scripts loaded by ``Services.mm.loadFrameScript``. Defines the environment for scripts loaded by ``Services.mm.loadFrameScript``.
jsm sysmjs
--- ---
Defines the environment for jsm files (javascript modules). Defines the environment for system module files (.sys.mjs).
privileged privileged
---------- ----------

View file

@ -1,23 +0,0 @@
mark-exported-symbols-as-used
=============================
Marks variables listed in ``EXPORTED_SYMBOLS`` as used so that ``no-unused-vars``
does not complain about them.
This rule also checks that ``EXPORTED_SYMBOLS`` is not defined using ``let`` as
``let`` isn't allowed as the lexical scope may die after the script executes.
Examples of incorrect code for this rule:
-----------------------------------------
.. code-block:: js
let EXPORTED_SYMBOLS = ["foo"];
Examples of correct code for this rule:
---------------------------------------
.. code-block:: js
var EXPORTED_SYMBOLS = ["foo"];
const EXPORTED_SYMBOLS = ["foo"];

View file

@ -1,22 +0,0 @@
reject-chromeutils-import-params
================================
``ChromeUtils.import`` used to be able to be called with two arguments, however
the second argument is no longer supported. Exports from modules should now be
explicit, and the imported symbols being accessed from the returned object.
Examples of incorrect code for this rule:
-----------------------------------------
.. code-block:: js
ChromeUtils.import("resource://gre/modules/AppConstants.jsm", this);
ChromeUtils.import("resource://gre/modules/AppConstants.jsm", null);
ChromeUtils.import("resource://gre/modules/AppConstants.jsm", {});
Examples of correct code for this rule:
---------------------------------------
.. code-block:: js
const { AppConstants } = ChromeUtils.import("resource://gre/modules/AppConstants.jsm");

View file

@ -1,27 +0,0 @@
reject-chromeutils-import
================================
While ``ChromeUtils.import`` supports the fallback to ESMified module,
in-tree files should use ``ChromeUtils.importESModule`` for ESMified modules.
Examples of incorrect code for this rule:
-----------------------------------------
.. code-block:: js
ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
ChromeUtils.defineModuleGetter(
obj, "AppConstants", "resource://gre/modules/AppConstants.jsm");
XPCOMUtils.defineLazyModuleGetters(
obj, { AppConstants: "resource://gre/modules/AppConstants.jsm" });
Examples of correct code for this rule:
---------------------------------------
.. code-block:: js
ChromeUtils.importESModule("resource://gre/modules/AppConstants.sys.mjs");
ChromeUtils.defineESModuleGetters(
obj, { AppConstants: "resource://gre/modules/AppConstants.sys.mjs" });

View file

@ -12,9 +12,6 @@ Examples of incorrect code for this rule:
ChromeUtils.defineESModuleGetters(lazy, { ChromeUtils.defineESModuleGetters(lazy, {
AppConstants: "resource://gre/modules/AppConstants.sys.mjs", AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
}); });
XPCOMUtils.defineLazyModuleGetters(lazy, {
XPCOMUtils: "resource://gre/modules/XPCOMUtils.jsm",
});
Examples of correct code for this rule: Examples of correct code for this rule:
--------------------------------------- ---------------------------------------
@ -22,9 +19,6 @@ Examples of correct code for this rule:
.. code-block:: js .. code-block:: js
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs"; import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
const { XPCOMUtils } = ChromeUtils.import( const { AppConstants } = ChromeUtils.importESModule(
"resource://gre/modules/XPCOMUtils.jsm" "resource://gre/modules/AppConstants.sys.mjs"
);
const { AppConstants } = ChromeUtils.import(
"resource://gre/modules/AppConstants.jsm"
); );

View file

@ -1,29 +0,0 @@
reject-global-this
======================
Rejects global ``this`` usage in JSM files. The global ``this`` is not
available in ESM, and this is a preparation for the migration.
Examples of incorrect code for this rule:
-----------------------------------------
.. code-block:: js
this.EXPORTED_SYMBOLS = ["foo"];
XPCOMUtils.defineLazyModuleGetters(this, {
AddonManager: "resource://gre/modules/AddonManager.jsm",
});
Examples of correct code for this rule:
---------------------------------------
.. code-block:: js
const EXPORTED_SYMBOLS = ["foo"];
const lazy = {};
XPCOMUtils.defineLazyModuleGetters(lazy, {
AddonManager: "resource://gre/modules/AddonManager.jsm",
});

View file

@ -1,19 +0,0 @@
use-chromeutils-import
======================
Require use of ``ChromeUtils.import`` rather than ``Components.utils.import``.
Examples of incorrect code for this rule:
-----------------------------------------
.. code-block:: js
Components.utils.import("resource://gre/modules/AppConstants.jsm", this);
Examples of correct code for this rule:
---------------------------------------
.. code-block:: js
ChromeUtils.import("resource://gre/modules/AppConstants.jsm", this);
ChromeUtils.defineModuleGetter(this, "AppConstants", "resource://gre/modules/AppConstants.jsm");

View file

@ -8,7 +8,6 @@ is created from a different context.
These files are covered: These files are covered:
- ``*.sys.mjs`` - ``*.sys.mjs``
- ``*.jsm``
- ``*.xhtml`` with ``there.is.only.xul`` - ``*.xhtml`` with ``there.is.only.xul``
- ``*.js`` with a heuristic - ``*.js`` with a heuristic

View file

@ -14,7 +14,6 @@
#include "mozilla/dom/Document.h" #include "mozilla/dom/Document.h"
#include "mozilla/dom/UserActivationIPCUtils.h" #include "mozilla/dom/UserActivationIPCUtils.h"
#include "mozilla/PermissionDelegateIPCUtils.h" #include "mozilla/PermissionDelegateIPCUtils.h"
#include "mozilla/RFPTargetIPCUtils.h"
#include "mozilla/StaticPrefs_dom.h" #include "mozilla/StaticPrefs_dom.h"
#include "mozilla/StaticPtr.h" #include "mozilla/StaticPtr.h"
#include "mozilla/ClearOnShutdown.h" #include "mozilla/ClearOnShutdown.h"
@ -22,6 +21,7 @@
#include "nsIScriptError.h" #include "nsIScriptError.h"
#include "nsIWebProgressListener.h" #include "nsIWebProgressListener.h"
#include "nsIXULRuntime.h" #include "nsIXULRuntime.h"
#include "nsRFPTargetSetIDL.h"
#include "nsRefPtrHashtable.h" #include "nsRefPtrHashtable.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
@ -78,6 +78,19 @@ bool WindowContext::IsInBFCache() {
return TopWindowContext()->GetWindowStateSaved(); return TopWindowContext()->GetWindowStateSaved();
} }
already_AddRefed<nsIRFPTargetSetIDL>
WindowContext::GetOverriddenFingerprintingSettingsWebIDL() const {
Maybe<RFPTargetSet> overriddenFingerprintingSettings =
GetOverriddenFingerprintingSettings();
if (overriddenFingerprintingSettings.isNothing()) {
return nullptr;
}
nsCOMPtr<nsIRFPTargetSetIDL> protections =
new nsRFPTargetSetIDL(overriddenFingerprintingSettings.ref());
return protections.forget();
}
nsGlobalWindowInner* WindowContext::GetInnerWindow() const { nsGlobalWindowInner* WindowContext::GetInnerWindow() const {
return mWindowGlobalChild ? mWindowGlobalChild->GetWindowGlobal() : nullptr; return mWindowGlobalChild ? mWindowGlobalChild->GetWindowGlobal() : nullptr;
} }
@ -241,7 +254,7 @@ bool WindowContext::CanSet(FieldIndex<IDX_ShouldResistFingerprinting>,
} }
bool WindowContext::CanSet(FieldIndex<IDX_OverriddenFingerprintingSettings>, bool WindowContext::CanSet(FieldIndex<IDX_OverriddenFingerprintingSettings>,
const Maybe<RFPTarget>& aValue, const Maybe<RFPTargetSet>& aValue,
ContentParent* aSource) { ContentParent* aSource) {
return CheckOnlyOwningProcessCanSet(aSource); return CheckOnlyOwningProcessCanSet(aSource);
} }

View file

@ -23,6 +23,7 @@ class nsGlobalWindowInner;
namespace mozilla { namespace mozilla {
class LogModule; class LogModule;
class nsRFPTargetSetIDL;
namespace dom { namespace dom {
@ -55,7 +56,7 @@ class BrowsingContextGroup;
* the Storage Access API */ \ * the Storage Access API */ \
FIELD(UsingStorageAccess, bool) \ FIELD(UsingStorageAccess, bool) \
FIELD(ShouldResistFingerprinting, bool) \ FIELD(ShouldResistFingerprinting, bool) \
FIELD(OverriddenFingerprintingSettings, Maybe<RFPTarget>) \ FIELD(OverriddenFingerprintingSettings, Maybe<RFPTargetSet>) \
FIELD(IsSecureContext, bool) \ FIELD(IsSecureContext, bool) \
FIELD(IsOriginalFrameSource, bool) \ FIELD(IsOriginalFrameSource, bool) \
/* Mixed-Content: If the corresponding documentURI is https, \ /* Mixed-Content: If the corresponding documentURI is https, \
@ -139,15 +140,8 @@ class WindowContext : public nsISupports, public nsWrapperCache {
bool UsingStorageAccess() const { return GetUsingStorageAccess(); } bool UsingStorageAccess() const { return GetUsingStorageAccess(); }
Nullable<uint64_t> GetOverriddenFingerprintingSettingsWebIDL() const { already_AddRefed<nsIRFPTargetSetIDL>
Maybe<RFPTarget> overriddenFingerprintingSettings = GetOverriddenFingerprintingSettingsWebIDL() const;
GetOverriddenFingerprintingSettings();
return overriddenFingerprintingSettings.isSome()
? Nullable<uint64_t>(
uint64_t(overriddenFingerprintingSettings.ref()))
: Nullable<uint64_t>();
}
nsGlobalWindowInner* GetInnerWindow() const; nsGlobalWindowInner* GetInnerWindow() const;
Document* GetDocument() const; Document* GetDocument() const;
@ -305,7 +299,7 @@ class WindowContext : public nsISupports, public nsWrapperCache {
bool CanSet(FieldIndex<IDX_ShouldResistFingerprinting>, bool CanSet(FieldIndex<IDX_ShouldResistFingerprinting>,
const bool& aShouldResistFingerprinting, ContentParent* aSource); const bool& aShouldResistFingerprinting, ContentParent* aSource);
bool CanSet(FieldIndex<IDX_OverriddenFingerprintingSettings>, bool CanSet(FieldIndex<IDX_OverriddenFingerprintingSettings>,
const Maybe<RFPTarget>& aValue, ContentParent* aSource); const Maybe<RFPTargetSet>& aValue, ContentParent* aSource);
bool CanSet(FieldIndex<IDX_IsSecureContext>, const bool& aIsSecureContext, bool CanSet(FieldIndex<IDX_IsSecureContext>, const bool& aIsSecureContext,
ContentParent* aSource); ContentParent* aSource);
bool CanSet(FieldIndex<IDX_IsOriginalFrameSource>, bool CanSet(FieldIndex<IDX_IsOriginalFrameSource>,

View file

@ -60,6 +60,7 @@
#include "mozilla/RemoteDecoderManagerChild.h" #include "mozilla/RemoteDecoderManagerChild.h"
#include "mozilla/KeySystemConfig.h" #include "mozilla/KeySystemConfig.h"
#include "mozilla/WheelHandlingHelper.h" #include "mozilla/WheelHandlingHelper.h"
#include "nsIRFPTargetSetIDL.h"
#include "nsContentSecurityUtils.h" #include "nsContentSecurityUtils.h"
#include "nsString.h" #include "nsString.h"
#include "nsNativeTheme.h" #include "nsNativeTheme.h"
@ -2317,7 +2318,7 @@ void ChromeUtils::GetAllPossibleUtilityActorNames(GlobalObject& aGlobal,
/* static */ /* static */
bool ChromeUtils::ShouldResistFingerprinting( bool ChromeUtils::ShouldResistFingerprinting(
GlobalObject& aGlobal, JSRFPTarget aTarget, GlobalObject& aGlobal, JSRFPTarget aTarget,
const Nullable<uint64_t>& aOverriddenFingerprintingSettings, nsIRFPTargetSetIDL* aOverriddenFingerprintingSettings,
const Optional<bool>& aIsPBM) { const Optional<bool>& aIsPBM) {
RFPTarget target; RFPTarget target;
switch (aTarget) { switch (aTarget) {
@ -2351,10 +2352,16 @@ bool ChromeUtils::ShouldResistFingerprinting(
} }
} }
Maybe<RFPTarget> overriddenFingerprintingSettings; Maybe<RFPTargetSet> overriddenFingerprintingSettings;
if (!aOverriddenFingerprintingSettings.IsNull()) { if (aOverriddenFingerprintingSettings) {
overriddenFingerprintingSettings.emplace( uint64_t low, hi;
RFPTarget(aOverriddenFingerprintingSettings.Value())); aOverriddenFingerprintingSettings->GetLow(&low);
aOverriddenFingerprintingSettings->GetHigh(&hi);
std::bitset<128> bitset;
bitset |= hi;
bitset <<= 64;
bitset |= low;
overriddenFingerprintingSettings.emplace(RFPTargetSet(bitset));
} }
// This global object appears to be the global window, not for individual // This global object appears to be the global window, not for individual

View file

@ -16,6 +16,8 @@
#include "nsIDOMProcessChild.h" #include "nsIDOMProcessChild.h"
#include "nsIDOMProcessParent.h" #include "nsIDOMProcessParent.h"
class nsIRFPTargetSetIDL;
namespace mozilla { namespace mozilla {
class ErrorResult; class ErrorResult;
@ -326,7 +328,7 @@ class ChromeUtils {
static bool ShouldResistFingerprinting( static bool ShouldResistFingerprinting(
GlobalObject& aGlobal, JSRFPTarget aTarget, GlobalObject& aGlobal, JSRFPTarget aTarget,
const Nullable<uint64_t>& aOverriddenFingerprintingSettings, nsIRFPTargetSetIDL* aOverriddenFingerprintingSettings,
const Optional<bool>& aIsPBM); const Optional<bool>& aIsPBM);
static void SanitizeTelemetryFileURL(GlobalObject& aGlobal, static void SanitizeTelemetryFileURL(GlobalObject& aGlobal,

View file

@ -4200,7 +4200,7 @@ class Document : public nsINode,
bool ShouldResistFingerprinting(RFPTarget aTarget) const; bool ShouldResistFingerprinting(RFPTarget aTarget) const;
bool IsInPrivateBrowsing() const; bool IsInPrivateBrowsing() const;
const Maybe<RFPTarget>& GetOverriddenFingerprintingSettings() const { const Maybe<RFPTargetSet>& GetOverriddenFingerprintingSettings() const {
return mOverriddenFingerprintingSettings; return mOverriddenFingerprintingSettings;
} }
@ -4986,7 +4986,7 @@ class Document : public nsINode,
// This will only get populated if these is one that comes from the local // This will only get populated if these is one that comes from the local
// fingerprinting protection override pref or WebCompat. Otherwise, a value of // fingerprinting protection override pref or WebCompat. Otherwise, a value of
// Nothing() indicates no overrides are present for this document. // Nothing() indicates no overrides are present for this document.
Maybe<RFPTarget> mOverriddenFingerprintingSettings; Maybe<RFPTargetSet> mOverriddenFingerprintingSettings;
uint8_t mXMLDeclarationBits; uint8_t mXMLDeclarationBits;

View file

@ -5495,7 +5495,7 @@ bool Element::Translate() const {
return true; return true;
} }
EditorBase* Element::GetEditorWithoutCreation() const { EditorBase* Element::GetExtantEditor() const {
if (!IsInComposedDoc()) { if (!IsInComposedDoc()) {
return nullptr; return nullptr;
} }
@ -5507,8 +5507,7 @@ EditorBase* Element::GetEditorWithoutCreation() const {
if (!isInDesignMode) { if (!isInDesignMode) {
if (const auto* textControlElement = TextControlElement::FromNode(this)) { if (const auto* textControlElement = TextControlElement::FromNode(this)) {
if (textControlElement->IsSingleLineTextControlOrTextArea()) { if (textControlElement->IsSingleLineTextControlOrTextArea()) {
return static_cast<const TextControlElement*>(this) return textControlElement->GetExtantTextEditor();
->GetTextEditorWithoutCreation();
} }
} }
} }
@ -5517,7 +5516,7 @@ EditorBase* Element::GetEditorWithoutCreation() const {
return nullptr; return nullptr;
} }
// FYI: This never creates HTMLEditor immediately. // FYI: This never creates HTMLEditor immediately.
nsDocShell* docShell = nsDocShell::Cast(OwnerDoc()->GetDocShell()); nsDocShell* const docShell = nsDocShell::Cast(OwnerDoc()->GetDocShell());
return docShell ? docShell->GetHTMLEditorInternal() : nullptr; return docShell ? docShell->GetHTMLEditorInternal() : nullptr;
} }

View file

@ -238,12 +238,8 @@ class TrustedHTMLOrNullIsEmptyString;
class TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString; class TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString;
// IID for the dom::Element interface // IID for the dom::Element interface
#define NS_ELEMENT_IID \ #define NS_ELEMENT_IID \
{ \ {0xc67ed254, 0xfd3b, 0x4b10, {0x96, 0xa2, 0xc5, 0x8b, 0x7b, 0x64, 0x97, 0xd1}}
0xc67ed254, 0xfd3b, 0x4b10, { \
0x96, 0xa2, 0xc5, 0x8b, 0x7b, 0x64, 0x97, 0xd1 \
} \
}
#define REFLECT_NULLABLE_DOMSTRING_ATTR(method, attr) \ #define REFLECT_NULLABLE_DOMSTRING_ATTR(method, attr) \
void Get##method(nsAString& aValue) const { \ void Get##method(nsAString& aValue) const { \
@ -1397,13 +1393,13 @@ class Element : public FragmentOrElement {
/** /**
* Get an editor which handles user inputs when this element has focus. * Get an editor which handles user inputs when this element has focus.
* If this is a text control, return a TextEditor if it's already created. * If this is a text control, return a TextEditor if it's already created and
* Otherwise, return nullptr. * it's not in the design mode.
* If this is not a text control but this is editable, return * If this is editable, return HTMLEditor which should've already been
* HTMLEditor which should've already been created. * created.
* Otherwise, return nullptr. * Otherwise, return nullptr.
*/ */
EditorBase* GetEditorWithoutCreation() const; EditorBase* GetExtantEditor() const;
private: private:
/** /**

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