Update On Thu Jun 16 20:31:13 CEST 2022
This commit is contained in:
parent
df6f62ff91
commit
b2b8c15115
548 changed files with 9615 additions and 6844 deletions
51
Cargo.lock
generated
51
Cargo.lock
generated
|
@ -99,9 +99,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "arbitrary"
|
||||
version = "1.1.0"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c38b6b6b79f671c25e1a3e785b7b82d7562ffc9cd3efdc98627e5668a2472490"
|
||||
checksum = "4f7487a7cc86cea29c97c91007ad21294f9959949577b305ae118b8c11738ccf"
|
||||
dependencies = [
|
||||
"derive_arbitrary",
|
||||
]
|
||||
|
@ -805,9 +805,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.2.0"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213"
|
||||
checksum = "5538cd660450ebeb4234cfecf8f2284b844ffc4c50531e66d584ad5b91293613"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
|
@ -1363,9 +1363,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "derive_arbitrary"
|
||||
version = "1.1.0"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98e23c06c035dac87bd802d98f368df73a7f2cb05a66ffbd1f377e821fac4af9"
|
||||
checksum = "91d001046c3cc126eb2ee9bdc946d9f482fe9e74d4a5ef191a6834fdbf84d45c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -2112,13 +2112,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.6"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad"
|
||||
checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"wasi",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2256,9 +2256,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "glean"
|
||||
version = "50.0.1"
|
||||
version = "50.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea3a101f9b9ccffbbcb7fe5159aabc22f7a5b8a266a9a810abff92ffe4b7bfc1"
|
||||
checksum = "0857be0c251ae1fc3b5672237c99f5115a6546cd8b171cb240173098ab5e9629"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"crossbeam-channel",
|
||||
|
@ -2276,9 +2276,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "glean-core"
|
||||
version = "50.0.1"
|
||||
version = "50.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e474434da0bdd88a97e06b9b47cd2eaa419e3707c21fee02f5c4d66577f3360"
|
||||
checksum = "f1bdfa0e2e6476190b4762c4cdc87c1a7a0347f601864b091cf9ad674a909c68"
|
||||
dependencies = [
|
||||
"android_logger",
|
||||
"bincode",
|
||||
|
@ -4584,9 +4584,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rust_decimal"
|
||||
version = "1.24.0"
|
||||
version = "1.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2ee7337df68898256ad0d4af4aad178210d9e44d2ff900ce44064a97cd86530"
|
||||
checksum = "34a3bb58e85333f1ab191bf979104b586ebd77475bc6681882825f4532dfe87c"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"num-traits",
|
||||
|
@ -4705,9 +4705,9 @@ checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af"
|
|||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.9"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd"
|
||||
checksum = "a41d061efea015927ac527063765e73601444cdc344ba855bc7bd44578b25e1c"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
@ -5251,7 +5251,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi",
|
||||
"wasi 0.10.0+wasi-snapshot-preview999",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
|
@ -5637,9 +5637,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
|
|||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee"
|
||||
checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
|
@ -5843,9 +5843,16 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.0+wasi-snapshot-preview1"
|
||||
version = "0.10.0+wasi-snapshot-preview999"
|
||||
dependencies = [
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
|
|
|
@ -135,6 +135,9 @@ parking_lot = { path = "build/rust/parking_lot" }
|
|||
# Override tinyvec with smallvec
|
||||
tinyvec = { path = "build/rust/tinyvec" }
|
||||
|
||||
# Patch wasi 0.10 to 0.11
|
||||
wasi = { path = "build/rust/wasi" }
|
||||
|
||||
# Patch autocfg to hide rustc output. Workaround for https://github.com/cuviper/autocfg/issues/30
|
||||
autocfg = { path = "third_party/rust/autocfg" }
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "nsEventShell.h"
|
||||
#include "DocAccessible.h"
|
||||
#include "DocAccessibleChild.h"
|
||||
#include "mozilla/StaticPrefs_accessibility.h"
|
||||
#include "nsAccessibilityService.h"
|
||||
#include "nsTextEquivUtils.h"
|
||||
#ifdef A11Y_LOG
|
||||
|
@ -307,6 +308,9 @@ void EventQueue::CoalesceSelChangeEvents(AccSelChangeEvent* aTailEvent,
|
|||
void EventQueue::ProcessEventQueue() {
|
||||
// Process only currently queued events.
|
||||
const nsTArray<RefPtr<AccEvent> > events = std::move(mEvents);
|
||||
nsTArray<uint64_t> selectedIDs;
|
||||
nsTArray<uint64_t> unselectedIDs;
|
||||
|
||||
uint32_t eventCount = events.Length();
|
||||
#ifdef A11Y_LOG
|
||||
if ((eventCount > 0 || mFocusEvent) && logging::IsEnabled(logging::eEvents)) {
|
||||
|
@ -336,48 +340,81 @@ void EventQueue::ProcessEventQueue() {
|
|||
|
||||
for (uint32_t idx = 0; idx < eventCount; idx++) {
|
||||
AccEvent* event = events[idx];
|
||||
if (event->mEventRule != AccEvent::eDoNotEmit) {
|
||||
LocalAccessible* target = event->GetAccessible();
|
||||
if (!target || target->IsDefunct()) continue;
|
||||
uint32_t eventType = event->mEventType;
|
||||
LocalAccessible* target = event->GetAccessible();
|
||||
if (!target || target->IsDefunct()) continue;
|
||||
|
||||
// Dispatch caret moved and text selection change events.
|
||||
if (event->mEventType ==
|
||||
nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED) {
|
||||
SelectionMgr()->ProcessTextSelChangeEvent(event);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Fire selected state change events in support to selection events.
|
||||
if (event->mEventType == nsIAccessibleEvent::EVENT_SELECTION_ADD) {
|
||||
nsEventShell::FireEvent(event->mAccessible, states::SELECTED, true,
|
||||
event->mIsFromUserInput);
|
||||
|
||||
} else if (event->mEventType ==
|
||||
nsIAccessibleEvent::EVENT_SELECTION_REMOVE) {
|
||||
nsEventShell::FireEvent(event->mAccessible, states::SELECTED, false,
|
||||
event->mIsFromUserInput);
|
||||
|
||||
} else if (event->mEventType == nsIAccessibleEvent::EVENT_SELECTION) {
|
||||
// Collect select changes
|
||||
if (IPCAccessibilityActive() &&
|
||||
StaticPrefs::accessibility_cache_enabled_AtStartup()) {
|
||||
if ((event->mEventRule == AccEvent::eDoNotEmit &&
|
||||
(eventType == nsIAccessibleEvent::EVENT_SELECTION_ADD ||
|
||||
eventType == nsIAccessibleEvent::EVENT_SELECTION_REMOVE ||
|
||||
eventType == nsIAccessibleEvent::EVENT_SELECTION)) ||
|
||||
eventType == nsIAccessibleEvent::EVENT_SELECTION_WITHIN) {
|
||||
// The selection even was either dropped or morphed to a
|
||||
// selection-within. We need to collect the items from all these events
|
||||
// and manually push their new state to the parent process.
|
||||
AccSelChangeEvent* selChangeEvent = downcast_accEvent(event);
|
||||
nsEventShell::FireEvent(event->mAccessible, states::SELECTED,
|
||||
(selChangeEvent->mSelChangeType ==
|
||||
AccSelChangeEvent::eSelectionAdd),
|
||||
event->mIsFromUserInput);
|
||||
|
||||
if (selChangeEvent->mPackedEvent) {
|
||||
nsEventShell::FireEvent(
|
||||
selChangeEvent->mPackedEvent->mAccessible, states::SELECTED,
|
||||
(selChangeEvent->mPackedEvent->mSelChangeType ==
|
||||
AccSelChangeEvent::eSelectionAdd),
|
||||
selChangeEvent->mPackedEvent->mIsFromUserInput);
|
||||
LocalAccessible* item = selChangeEvent->mItem;
|
||||
uint64_t itemID =
|
||||
item->IsDoc() ? 0 : reinterpret_cast<uint64_t>(item->UniqueID());
|
||||
bool selected =
|
||||
selChangeEvent->mSelChangeType == AccSelChangeEvent::eSelectionAdd;
|
||||
if (selected) {
|
||||
selectedIDs.AppendElement(itemID);
|
||||
} else {
|
||||
unselectedIDs.AppendElement(itemID);
|
||||
}
|
||||
}
|
||||
|
||||
nsEventShell::FireEvent(event);
|
||||
}
|
||||
|
||||
if (event->mEventRule == AccEvent::eDoNotEmit) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Dispatch caret moved and text selection change events.
|
||||
if (eventType == nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED) {
|
||||
SelectionMgr()->ProcessTextSelChangeEvent(event);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Fire selected state change events in support to selection events.
|
||||
if (eventType == nsIAccessibleEvent::EVENT_SELECTION_ADD) {
|
||||
nsEventShell::FireEvent(event->mAccessible, states::SELECTED, true,
|
||||
event->mIsFromUserInput);
|
||||
|
||||
} else if (eventType == nsIAccessibleEvent::EVENT_SELECTION_REMOVE) {
|
||||
nsEventShell::FireEvent(event->mAccessible, states::SELECTED, false,
|
||||
event->mIsFromUserInput);
|
||||
|
||||
} else if (eventType == nsIAccessibleEvent::EVENT_SELECTION) {
|
||||
AccSelChangeEvent* selChangeEvent = downcast_accEvent(event);
|
||||
nsEventShell::FireEvent(
|
||||
event->mAccessible, states::SELECTED,
|
||||
(selChangeEvent->mSelChangeType == AccSelChangeEvent::eSelectionAdd),
|
||||
event->mIsFromUserInput);
|
||||
|
||||
if (selChangeEvent->mPackedEvent) {
|
||||
nsEventShell::FireEvent(selChangeEvent->mPackedEvent->mAccessible,
|
||||
states::SELECTED,
|
||||
(selChangeEvent->mPackedEvent->mSelChangeType ==
|
||||
AccSelChangeEvent::eSelectionAdd),
|
||||
selChangeEvent->mPackedEvent->mIsFromUserInput);
|
||||
}
|
||||
}
|
||||
|
||||
nsEventShell::FireEvent(event);
|
||||
|
||||
if (!mDocument) return;
|
||||
}
|
||||
|
||||
if (mDocument && IPCAccessibilityActive() &&
|
||||
StaticPrefs::accessibility_cache_enabled_AtStartup() &&
|
||||
(!selectedIDs.IsEmpty() || !unselectedIDs.IsEmpty())) {
|
||||
DocAccessibleChild* ipcDoc = mDocument->IPCDoc();
|
||||
ipcDoc->SendSelectedAccessiblesChanged(selectedIDs, unselectedIDs);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace a11y
|
||||
|
|
|
@ -97,6 +97,10 @@ bool Accessible::HasGenericType(AccGenericType aType) const {
|
|||
(roleMapEntry && roleMapEntry->IsOfType(aType));
|
||||
}
|
||||
|
||||
nsIntRect Accessible::BoundsInCSSPixels() const {
|
||||
return BoundsInAppUnits().ToNearestPixels(AppUnitsPerCSSPixel());
|
||||
}
|
||||
|
||||
LayoutDeviceIntSize Accessible::Size() const { return Bounds().Size(); }
|
||||
|
||||
LayoutDeviceIntPoint Accessible::Position(uint32_t aCoordType) {
|
||||
|
|
|
@ -197,6 +197,16 @@ class Accessible {
|
|||
*/
|
||||
virtual LayoutDeviceIntRect Bounds() const = 0;
|
||||
|
||||
/**
|
||||
* Return boundaries in screen coordinates in app units.
|
||||
*/
|
||||
virtual nsRect BoundsInAppUnits() const = 0;
|
||||
|
||||
/**
|
||||
* Return boundaries in screen coordinates in CSS pixels.
|
||||
*/
|
||||
virtual nsIntRect BoundsInCSSPixels() const;
|
||||
|
||||
/**
|
||||
* Returns text of accessible if accessible has text role otherwise empty
|
||||
* string.
|
||||
|
|
|
@ -789,10 +789,6 @@ LayoutDeviceIntRect LocalAccessible::Bounds() const {
|
|||
BoundsInAppUnits(), mDoc->PresContext()->AppUnitsPerDevPixel());
|
||||
}
|
||||
|
||||
nsIntRect LocalAccessible::BoundsInCSSPixels() const {
|
||||
return BoundsInAppUnits().ToNearestPixels(AppUnitsPerCSSPixel());
|
||||
}
|
||||
|
||||
void LocalAccessible::SetSelected(bool aSelect) {
|
||||
if (!HasOwnContent()) return;
|
||||
|
||||
|
|
|
@ -405,18 +405,10 @@ class LocalAccessible : public nsISupports, public Accessible {
|
|||
virtual void AppendTextTo(nsAString& aText, uint32_t aStartOffset = 0,
|
||||
uint32_t aLength = UINT32_MAX) override;
|
||||
|
||||
/**
|
||||
* Return boundaries in screen coordinates in app units.
|
||||
*/
|
||||
virtual nsRect BoundsInAppUnits() const;
|
||||
virtual nsRect BoundsInAppUnits() const override;
|
||||
|
||||
virtual LayoutDeviceIntRect Bounds() const override;
|
||||
|
||||
/**
|
||||
* Return boundaries in screen coordinates in CSS pixels.
|
||||
*/
|
||||
virtual nsIntRect BoundsInCSSPixels() const;
|
||||
|
||||
/**
|
||||
* Return boundaries rect relative the bounding frame.
|
||||
*/
|
||||
|
|
|
@ -619,6 +619,41 @@ mozilla::ipc::IPCResult DocAccessibleParent::RecvCache(
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult DocAccessibleParent::RecvSelectedAccessiblesChanged(
|
||||
nsTArray<uint64_t>&& aSelectedIDs, nsTArray<uint64_t>&& aUnselectedIDs) {
|
||||
ACQUIRE_ANDROID_LOCK
|
||||
if (mShutdown) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
for (auto& id : aSelectedIDs) {
|
||||
RemoteAccessible* remote = GetAccessible(id);
|
||||
if (!remote) {
|
||||
MOZ_ASSERT_UNREACHABLE("No remote found!");
|
||||
continue;
|
||||
}
|
||||
|
||||
remote->UpdateStateCache(states::SELECTED, true);
|
||||
}
|
||||
|
||||
for (auto& id : aUnselectedIDs) {
|
||||
RemoteAccessible* remote = GetAccessible(id);
|
||||
if (!remote) {
|
||||
MOZ_ASSERT_UNREACHABLE("No remote found!");
|
||||
continue;
|
||||
}
|
||||
|
||||
remote->UpdateStateCache(states::SELECTED, false);
|
||||
}
|
||||
|
||||
if (nsCOMPtr<nsIObserverService> obsService =
|
||||
services::GetObserverService()) {
|
||||
obsService->NotifyObservers(nullptr, NS_ACCESSIBLE_CACHE_TOPIC, nullptr);
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult DocAccessibleParent::RecvAccessiblesWillMove(
|
||||
nsTArray<uint64_t>&& aIDs) {
|
||||
for (uint64_t id : aIDs) {
|
||||
|
|
|
@ -138,6 +138,10 @@ class DocAccessibleParent : public RemoteAccessible,
|
|||
const mozilla::a11y::CacheUpdateType& aUpdateType,
|
||||
nsTArray<CacheData>&& aData, const bool& aFinal) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvSelectedAccessiblesChanged(
|
||||
nsTArray<uint64_t>&& aSelectedIDs,
|
||||
nsTArray<uint64_t>&& aUnselectedIDs) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvAccessiblesWillMove(
|
||||
nsTArray<uint64_t>&& aIDs) override;
|
||||
|
||||
|
|
|
@ -457,7 +457,7 @@ void RemoteAccessibleBase<Derived>::ApplyScrollOffset(nsRect& aBounds) const {
|
|||
}
|
||||
|
||||
template <class Derived>
|
||||
nsRect RemoteAccessibleBase<Derived>::GetBoundsInAppUnits() const {
|
||||
nsRect RemoteAccessibleBase<Derived>::BoundsInAppUnits() const {
|
||||
dom::CanonicalBrowsingContext* cbc =
|
||||
static_cast<dom::BrowserParent*>(mDoc->Manager())
|
||||
->GetBrowsingContext()
|
||||
|
|
|
@ -181,7 +181,7 @@ class RemoteAccessibleBase : public Accessible, public HyperTextAccessibleBase {
|
|||
|
||||
virtual LayoutDeviceIntRect Bounds() const override;
|
||||
|
||||
nsRect GetBoundsInAppUnits() const;
|
||||
virtual nsRect BoundsInAppUnits() const override;
|
||||
|
||||
virtual uint64_t State() override;
|
||||
|
||||
|
|
|
@ -202,7 +202,7 @@ Accessible* ChildAtPoint(
|
|||
int32_t aX, int32_t aY,
|
||||
LocalAccessible::EWhichChildAtPoint aWhichChild) override;
|
||||
LayoutDeviceIntRect Bounds() const override;
|
||||
nsIntRect BoundsInCSSPixels();
|
||||
virtual nsIntRect BoundsInCSSPixels() const override;
|
||||
|
||||
void Language(nsString& aLocale);
|
||||
void DocType(nsString& aType);
|
||||
|
|
|
@ -135,6 +135,11 @@ parent:
|
|||
*/
|
||||
async Cache(CacheUpdateType aUpdateType, CacheData[] aData, bool aFinal);
|
||||
|
||||
/*
|
||||
* Lists of accessibles that either gained or lost a selected state.
|
||||
*/
|
||||
async SelectedAccessiblesChanged(uint64_t[] aSelectedIDs, uint64_t[] aUnselectedIDs);
|
||||
|
||||
/*
|
||||
* Tell the parent process that the given Accessibles are about to be moved
|
||||
* via subsequent hide and show events.
|
||||
|
|
|
@ -989,7 +989,11 @@ LayoutDeviceIntRect RemoteAccessible::Bounds() const {
|
|||
return rect;
|
||||
}
|
||||
|
||||
nsIntRect RemoteAccessible::BoundsInCSSPixels() {
|
||||
nsIntRect RemoteAccessible::BoundsInCSSPixels() const {
|
||||
if (StaticPrefs::accessibility_cache_enabled_AtStartup()) {
|
||||
return RemoteAccessibleBase<RemoteAccessible>::BoundsInCSSPixels();
|
||||
}
|
||||
|
||||
nsIntRect rect;
|
||||
Unused << mDoc->SendExtentsInCSSPixels(mID, &rect.x, &rect.y, &rect.width,
|
||||
&rect.height);
|
||||
|
|
|
@ -102,6 +102,11 @@ parent:
|
|||
*/
|
||||
async Cache(CacheUpdateType aUpdateType, CacheData[] aData, bool aFinal);
|
||||
|
||||
/*
|
||||
* Lists of accessibles that either gained or lost a selected state.
|
||||
*/
|
||||
async SelectedAccessiblesChanged(uint64_t[] aSelectedIDs, uint64_t[] aUnselectedIDs);
|
||||
|
||||
/*
|
||||
* Tell the parent process that the given Accessibles are about to be moved
|
||||
* via subsequent hide and show events.
|
||||
|
|
|
@ -252,7 +252,11 @@ LayoutDeviceIntRect RemoteAccessible::Bounds() const {
|
|||
return rect;
|
||||
}
|
||||
|
||||
nsIntRect RemoteAccessible::BoundsInCSSPixels() {
|
||||
nsIntRect RemoteAccessible::BoundsInCSSPixels() const {
|
||||
if (StaticPrefs::accessibility_cache_enabled_AtStartup()) {
|
||||
return RemoteAccessibleBase<RemoteAccessible>::BoundsInCSSPixels();
|
||||
}
|
||||
|
||||
RefPtr<IGeckoCustom> custom = QueryInterface<IGeckoCustom>(this);
|
||||
if (!custom) {
|
||||
return nsIntRect();
|
||||
|
|
|
@ -254,3 +254,46 @@ addAccessibleTask(
|
|||
remoteIframe: !isWinNoCache,
|
||||
}
|
||||
);
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
// multiselect with coalesced selection event
|
||||
addAccessibleTask(
|
||||
`<select id="listbox" size="4" multiple="true">
|
||||
<option id="item1">option1</option>
|
||||
<option id="item2">option2</option>
|
||||
<option id="item3">option3</option>
|
||||
<option id="item4">option4</option>
|
||||
<option id="item5">option5</option>
|
||||
<option id="item6">option6</option>
|
||||
<option id="item7">option7</option>
|
||||
<option id="item8">option8</option>
|
||||
<option id="item9">option9</option>
|
||||
</select>`,
|
||||
async function(browser, docAcc) {
|
||||
info("select@size='4' multiselect with coalesced selection event");
|
||||
let select = findAccessibleChildByID(docAcc, "listbox", [
|
||||
nsIAccessibleSelectable,
|
||||
]);
|
||||
await testMultiSelectable(
|
||||
select,
|
||||
[
|
||||
"item1",
|
||||
"item2",
|
||||
"item3",
|
||||
"item4",
|
||||
"item5",
|
||||
"item6",
|
||||
"item7",
|
||||
"item8",
|
||||
"item9",
|
||||
],
|
||||
"select@size='4' multiselect with coalesced selection event "
|
||||
);
|
||||
},
|
||||
{
|
||||
chrome: false,
|
||||
topLevel: true,
|
||||
iframe: false,
|
||||
remoteIframe: false,
|
||||
}
|
||||
);
|
||||
|
|
|
@ -65,30 +65,25 @@ async function testMultiSelectable(widget, selectableChildren, msg = "") {
|
|||
promise = multipleSelectionChanged(widget, selectableChildren, true);
|
||||
let success = widget.selectAll();
|
||||
ok(success, `${msg}: selectAll success`);
|
||||
let coalesced = await promise;
|
||||
if (isRemote && coalesced && isCacheEnabled) {
|
||||
todo_is(
|
||||
widget.selectedItemCount,
|
||||
await promise;
|
||||
if (isRemote && isCacheEnabled) {
|
||||
await untilCacheIs(
|
||||
() => widget.selectedItemCount,
|
||||
selectableChildren.length,
|
||||
"Bug 1755377: Coalesced SELECTION_WITHIN doesn't update cache"
|
||||
"Selection cache updated"
|
||||
);
|
||||
// We bail early here because the cache is out of sync.
|
||||
return;
|
||||
}
|
||||
|
||||
testSelectableSelection(widget, selectableChildren, `${msg}: selectAll`);
|
||||
|
||||
promise = multipleSelectionChanged(widget, selectableChildren, false);
|
||||
widget.unselectAll();
|
||||
coalesced = await promise;
|
||||
if (isRemote && coalesced && isCacheEnabled) {
|
||||
todo_is(
|
||||
widget.selectedItemCount,
|
||||
await promise;
|
||||
if (isRemote && isCacheEnabled) {
|
||||
await untilCacheIs(
|
||||
() => widget.selectedItemCount,
|
||||
0,
|
||||
"Coalesced SELECTION_WITHIN doesn't update cache"
|
||||
"Selection cache updated"
|
||||
);
|
||||
// We bail early here because the cache is out of sync.
|
||||
return;
|
||||
}
|
||||
testSelectableSelection(widget, [], `${msg}: selectAll`);
|
||||
}
|
||||
|
|
|
@ -435,13 +435,7 @@ xpcAccessible::GetBounds(int32_t* aX, int32_t* aY, int32_t* aWidth,
|
|||
|
||||
if (!IntlGeneric()) return NS_ERROR_FAILURE;
|
||||
|
||||
LayoutDeviceIntRect rect;
|
||||
if (LocalAccessible* acc = IntlGeneric()->AsLocal()) {
|
||||
rect = acc->Bounds();
|
||||
} else {
|
||||
rect = IntlGeneric()->AsRemote()->Bounds();
|
||||
}
|
||||
|
||||
LayoutDeviceIntRect rect = IntlGeneric()->Bounds();
|
||||
rect.GetRect(aX, aY, aWidth, aHeight);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -462,13 +456,7 @@ xpcAccessible::GetBoundsInCSSPixels(int32_t* aX, int32_t* aY, int32_t* aWidth,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsIntRect rect;
|
||||
if (LocalAccessible* acc = IntlGeneric()->AsLocal()) {
|
||||
rect = acc->BoundsInCSSPixels();
|
||||
} else {
|
||||
rect = IntlGeneric()->AsRemote()->BoundsInCSSPixels();
|
||||
}
|
||||
|
||||
nsIntRect rect = IntlGeneric()->BoundsInCSSPixels();
|
||||
rect.GetRect(aX, aY, aWidth, aHeight);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -27,9 +27,6 @@ class AboutPrivateBrowsingChild extends RemotePageChild {
|
|||
super.actorCreated();
|
||||
let window = this.contentWindow;
|
||||
|
||||
Cu.exportFunction(this.PrivateBrowsingFeatureConfig.bind(this), window, {
|
||||
defineAs: "PrivateBrowsingFeatureConfig",
|
||||
});
|
||||
Cu.exportFunction(this.PrivateBrowsingRecordClick.bind(this), window, {
|
||||
defineAs: "PrivateBrowsingRecordClick",
|
||||
});
|
||||
|
@ -48,10 +45,9 @@ class AboutPrivateBrowsingChild extends RemotePageChild {
|
|||
}
|
||||
|
||||
PrivateBrowsingRecordClick(source) {
|
||||
const experiment =
|
||||
lazy.ExperimentAPI.getExperimentMetaData({
|
||||
featureId: "privatebrowsing",
|
||||
}) || lazy.ExperimentAPI.getExperimentMetaData({ featureId: "pbNewtab" });
|
||||
const experiment = lazy.ExperimentAPI.getExperimentMetaData({
|
||||
featureId: "pbNewtab",
|
||||
});
|
||||
if (experiment) {
|
||||
Services.telemetry.recordEvent("aboutprivatebrowsing", "click", source);
|
||||
}
|
||||
|
@ -66,19 +62,4 @@ class AboutPrivateBrowsingChild extends RemotePageChild {
|
|||
PrivateBrowsingExposureTelemetry() {
|
||||
lazy.NimbusFeatures.pbNewtab.recordExposureEvent({ once: false });
|
||||
}
|
||||
|
||||
PrivateBrowsingFeatureConfig() {
|
||||
const config = lazy.NimbusFeatures.privatebrowsing.getAllVariables() || {};
|
||||
|
||||
lazy.NimbusFeatures.privatebrowsing.recordExposureEvent();
|
||||
|
||||
// Format urls if any are defined
|
||||
["infoLinkUrl", "promoLinkUrl"].forEach(key => {
|
||||
if (config[key]) {
|
||||
config[key] = Services.urlFormatter.formatURL(config[key]);
|
||||
}
|
||||
});
|
||||
|
||||
return Cu.cloneInto(config, this.contentWindow);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
Cu.importGlobalProperties(["fetch"]);
|
||||
|
||||
var EXPORTED_SYMBOLS = ["AboutProtectionsParent"];
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
|
|
|
@ -115,6 +115,8 @@ class ClickHandlerParent extends JSWindowActorParent {
|
|||
csp: data.csp ? lazy.E10SUtils.deserializeCSP(data.csp) : null,
|
||||
frameID: data.frameID,
|
||||
openerBrowser: browser,
|
||||
// The child ensures that untrusted events have a valid user activation.
|
||||
hasValidUserGestureActivation: true,
|
||||
};
|
||||
|
||||
// The new tab/window must use the same userContextId.
|
||||
|
|
|
@ -1011,9 +1011,6 @@ pref("plugins.show_infobar", false);
|
|||
pref("plugin.default.state", 1);
|
||||
#endif
|
||||
|
||||
// Enables the download and use of the flash blocklists.
|
||||
pref("plugins.flashBlock.enabled", true);
|
||||
|
||||
// Prefer HTML5 video over Flash content, and don't
|
||||
// load plugin instances with no src declared.
|
||||
// These prefs are documented in details on all.js.
|
||||
|
@ -1223,8 +1220,6 @@ pref("browser.bookmarks.editDialog.maxRecentFolders", 7);
|
|||
// just save on Accept, once the project is complete.
|
||||
pref("browser.bookmarks.editDialog.delayedApply.enabled", false);
|
||||
|
||||
pref("dom.ipc.shims.enabledWarnings", false);
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
// This controls the strength of the Windows content process sandbox for
|
||||
// testing purposes. This will require a restart.
|
||||
|
@ -1609,6 +1604,8 @@ pref("browser.aboutwelcome.enabled", true);
|
|||
// Used to set multistage welcome UX
|
||||
pref("browser.aboutwelcome.screens", "");
|
||||
pref("browser.aboutwelcome.skipFocus", true);
|
||||
// Used to enable template for MR 2022 Onboarding
|
||||
pref("browser.aboutwelcome.templateMR", false);
|
||||
|
||||
// The pref that controls if the What's New panel is enabled.
|
||||
pref("browser.messaging-system.whatsNewPanel.enabled", true);
|
||||
|
|
|
@ -176,8 +176,8 @@ panelview[mainview] > .panel-header {
|
|||
}
|
||||
|
||||
#tabbrowser-tabs[hasadjacentnewtabbutton]:not([overflow="true"]) ~ #new-tab-button,
|
||||
#tabbrowser-tabs[overflow="true"] > #tabbrowser-arrowscrollbox > #tabs-newtab-button,
|
||||
#tabbrowser-tabs:not([hasadjacentnewtabbutton]) > #tabbrowser-arrowscrollbox > #tabs-newtab-button,
|
||||
#tabbrowser-tabs[overflow="true"] > #tabbrowser-arrowscrollbox > #tabbrowser-arrowscrollbox-periphery > #tabs-newtab-button,
|
||||
#tabbrowser-tabs:not([hasadjacentnewtabbutton]) > #tabbrowser-arrowscrollbox > #tabbrowser-arrowscrollbox-periphery > #tabs-newtab-button,
|
||||
#TabsToolbar[customizing="true"] #tabs-newtab-button {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -1508,11 +1508,13 @@ function _loadURI(browser, uri, params = {}) {
|
|||
userContextId,
|
||||
csp,
|
||||
remoteTypeOverride,
|
||||
hasValidUserGestureActivation,
|
||||
} = params || {};
|
||||
let loadFlags =
|
||||
params.loadFlags || params.flags || Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
|
||||
let hasValidUserGestureActivation =
|
||||
hasValidUserGestureActivation ??=
|
||||
document.hasValidTransientUserGestureActivation;
|
||||
|
||||
if (!triggeringPrincipal) {
|
||||
throw new Error("Must load with a triggering Principal");
|
||||
}
|
||||
|
@ -2245,7 +2247,7 @@ var gBrowserInit = {
|
|||
});
|
||||
} catch (e) {}
|
||||
} else if (window.arguments.length >= 3) {
|
||||
// window.arguments[1]: unused (bug 871161)
|
||||
// window.arguments[1]: extraOptions (nsIPropertyBag)
|
||||
// [2]: referrerInfo (nsIReferrerInfo)
|
||||
// [3]: postData (nsIInputStream)
|
||||
// [4]: allowThirdPartyFixup (bool)
|
||||
|
@ -2260,23 +2262,50 @@ var gBrowserInit = {
|
|||
window.arguments[5] != undefined
|
||||
? window.arguments[5]
|
||||
: Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID;
|
||||
loadURI(
|
||||
uriToLoad,
|
||||
window.arguments[2] || null,
|
||||
window.arguments[3] || null,
|
||||
window.arguments[4] || false,
|
||||
userContextId,
|
||||
// pass the origin principal (if any) and force its use to create
|
||||
// an initial about:blank viewer if present:
|
||||
window.arguments[6],
|
||||
window.arguments[7],
|
||||
!!window.arguments[6],
|
||||
window.arguments[8],
|
||||
// TODO fix allowInheritPrincipal to default to false.
|
||||
// Default to true unless explicitly set to false because of bug 1475201.
|
||||
window.arguments[9] !== false,
|
||||
window.arguments[10]
|
||||
);
|
||||
|
||||
let hasValidUserGestureActivation = undefined;
|
||||
let fromExternal = undefined;
|
||||
if (window.arguments[1]) {
|
||||
if (!(window.arguments[1] instanceof Ci.nsIPropertyBag2)) {
|
||||
throw new Error(
|
||||
"window.arguments[1] must be null or Ci.nsIPropertyBag2!"
|
||||
);
|
||||
}
|
||||
|
||||
let extraOptions = window.arguments[1];
|
||||
if (extraOptions.hasKey("hasValidUserGestureActivation")) {
|
||||
hasValidUserGestureActivation = extraOptions.getPropertyAsBool(
|
||||
"hasValidUserGestureActivation"
|
||||
);
|
||||
}
|
||||
if (extraOptions.hasKey("fromExternal")) {
|
||||
fromExternal = extraOptions.getPropertyAsBool("fromExternal");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
openLinkIn(uriToLoad, "current", {
|
||||
referrerInfo: window.arguments[2] || null,
|
||||
postData: window.arguments[3] || null,
|
||||
allowThirdPartyFixup: window.arguments[4] || false,
|
||||
userContextId,
|
||||
// pass the origin principal (if any) and force its use to create
|
||||
// an initial about:blank viewer if present:
|
||||
originPrincipal: window.arguments[6],
|
||||
originStoragePrincipal: window.arguments[7],
|
||||
triggeringPrincipal: window.arguments[8],
|
||||
// TODO fix allowInheritPrincipal to default to false.
|
||||
// Default to true unless explicitly set to false because of bug 1475201.
|
||||
allowInheritPrincipal: window.arguments[9] !== false,
|
||||
csp: window.arguments[10],
|
||||
forceAboutBlankViewerInCurrent: !!window.arguments[6],
|
||||
hasValidUserGestureActivation,
|
||||
fromExternal,
|
||||
});
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
|
||||
window.focus();
|
||||
} else {
|
||||
// Note: loadOneOrMoreURIs *must not* be called if window.arguments.length >= 3.
|
||||
|
@ -6272,13 +6301,18 @@ nsBrowserAccess.prototype = {
|
|||
// Pass all params to openDialog to ensure that "url" isn't passed through
|
||||
// loadOneOrMoreURIs, which splits based on "|"
|
||||
try {
|
||||
let extraOptions = Cc[
|
||||
"@mozilla.org/hash-property-bag;1"
|
||||
].createInstance(Ci.nsIWritablePropertyBag2);
|
||||
extraOptions.setPropertyAsBool("fromExternal", isExternal);
|
||||
|
||||
openDialog(
|
||||
AppConstants.BROWSER_CHROME_URL,
|
||||
"_blank",
|
||||
features,
|
||||
// window.arguments
|
||||
url,
|
||||
null,
|
||||
extraOptions,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
|
|
|
@ -55,12 +55,15 @@
|
|||
# the current structure that we may want to revisit.
|
||||
<arrowscrollbox id="tabbrowser-arrowscrollbox" orient="horizontal" flex="1" style="min-width: 1px;" clicktoscroll="true" scrolledtostart="true" scrolledtoend="true">
|
||||
<tab is="tabbrowser-tab" class="tabbrowser-tab" selected="true" visuallyselected="true" fadein="true"/>
|
||||
<toolbarbutton id="tabs-newtab-button"
|
||||
class="toolbarbutton-1"
|
||||
command="cmd_newNavigatorTab"
|
||||
onclick="checkForMiddleClick(this, event);"
|
||||
tooltip="dynamic-shortcut-tooltip"/>
|
||||
<spacer class="closing-tabs-spacer" style="width: 0;"/>
|
||||
<hbox id="tabbrowser-arrowscrollbox-periphery">
|
||||
<toolbartabstop/>
|
||||
<toolbarbutton id="tabs-newtab-button"
|
||||
class="toolbarbutton-1"
|
||||
command="cmd_newNavigatorTab"
|
||||
onclick="checkForMiddleClick(this, event);"
|
||||
tooltip="dynamic-shortcut-tooltip"/>
|
||||
<spacer class="closing-tabs-spacer" style="width: 0;"/>
|
||||
</hbox>
|
||||
</arrowscrollbox>
|
||||
<html:span id="tabbrowser-tab-a11y-desc" hidden="true"/>
|
||||
</tabs>
|
||||
|
|
|
@ -1309,6 +1309,7 @@ class nsContextMenu {
|
|||
triggeringPrincipal: this.principal,
|
||||
csp: this.csp,
|
||||
frameID: this.contentData.frameID,
|
||||
hasValidUserGestureActivation: true,
|
||||
};
|
||||
for (let p in extra) {
|
||||
params[p] = extra[p];
|
||||
|
|
|
@ -1012,12 +1012,11 @@
|
|||
return this.querySelector("#tabs-newtab-button");
|
||||
}
|
||||
|
||||
// Accessor for tabs. arrowScrollbox has two non-tab elements at the
|
||||
// end, everything else is <tab>s
|
||||
// Accessor for tabs. arrowScrollbox has a container for non-tab elements
|
||||
// at the end, everything else is <tab>s.
|
||||
get allTabs() {
|
||||
let children = Array.from(this.arrowScrollbox.children);
|
||||
children.pop();
|
||||
children.pop();
|
||||
return children;
|
||||
}
|
||||
|
||||
|
@ -1032,8 +1031,8 @@
|
|||
|
||||
let { arrowScrollbox } = this;
|
||||
if (node == null) {
|
||||
// we have a toolbarbutton and a space at the end of the scrollbox
|
||||
node = arrowScrollbox.lastChild.previousSibling;
|
||||
// We have a container for non-tab elements at the end of the scrollbox.
|
||||
node = arrowScrollbox.lastChild;
|
||||
}
|
||||
return arrowScrollbox.insertBefore(tab, node);
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ tabpanels {
|
|||
pointer-events: none;
|
||||
}
|
||||
|
||||
#tabbrowser-arrowscrollbox:not(:hover) > .closing-tabs-spacer {
|
||||
#tabbrowser-arrowscrollbox:not(:hover) > #tabbrowser-arrowscrollbox-periphery > .closing-tabs-spacer {
|
||||
transition: width .15s ease-out;
|
||||
}
|
||||
|
||||
|
|
|
@ -409,12 +409,17 @@ function openLinkIn(url, where, params) {
|
|||
);
|
||||
wuri.data = url;
|
||||
|
||||
let charset = null;
|
||||
if (aCharset) {
|
||||
charset = Cc["@mozilla.org/supports-string;1"].createInstance(
|
||||
Ci.nsISupportsString
|
||||
let extraOptions = Cc["@mozilla.org/hash-property-bag;1"].createInstance(
|
||||
Ci.nsIWritablePropertyBag2
|
||||
);
|
||||
if (params.hasValidUserGestureActivation !== undefined) {
|
||||
extraOptions.setPropertyAsBool(
|
||||
"hasValidUserGestureActivation",
|
||||
params.hasValidUserGestureActivation
|
||||
);
|
||||
charset.data = "charset=" + aCharset;
|
||||
}
|
||||
if (params.fromExternal !== undefined) {
|
||||
extraOptions.setPropertyAsBool("fromExternal", params.fromExternal);
|
||||
}
|
||||
|
||||
var allowThirdPartyFixupSupports = Cc[
|
||||
|
@ -428,7 +433,7 @@ function openLinkIn(url, where, params) {
|
|||
userContextIdSupports.data = aUserContextId;
|
||||
|
||||
sa.appendElement(wuri);
|
||||
sa.appendElement(charset);
|
||||
sa.appendElement(extraOptions);
|
||||
sa.appendElement(aReferrerInfo);
|
||||
sa.appendElement(aPostData);
|
||||
sa.appendElement(allowThirdPartyFixupSupports);
|
||||
|
@ -579,6 +584,9 @@ function openLinkIn(url, where, params) {
|
|||
if (aForceAllowDataURI) {
|
||||
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FORCE_ALLOW_DATA_URI;
|
||||
}
|
||||
if (params.fromExternal) {
|
||||
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL;
|
||||
}
|
||||
|
||||
let { URI_INHERITS_SECURITY_CONTEXT } = Ci.nsIProtocolHandler;
|
||||
if (
|
||||
|
@ -600,6 +608,7 @@ function openLinkIn(url, where, params) {
|
|||
referrerInfo: aReferrerInfo,
|
||||
postData: aPostData,
|
||||
userContextId: aUserContextId,
|
||||
hasValidUserGestureActivation: params.hasValidUserGestureActivation,
|
||||
});
|
||||
if (aResolveOnContentBrowserReady) {
|
||||
aResolveOnContentBrowserReady(targetBrowser);
|
||||
|
@ -636,6 +645,7 @@ function openLinkIn(url, where, params) {
|
|||
csp: aCsp,
|
||||
focusUrlBar,
|
||||
openerBrowser: params.openerBrowser,
|
||||
fromExternal: params.fromExternal,
|
||||
});
|
||||
targetBrowser = tabUsedForLoad.linkedBrowser;
|
||||
|
||||
|
|
|
@ -250,12 +250,17 @@ function openBrowserWindow(
|
|||
});
|
||||
args = [uriArray];
|
||||
} else {
|
||||
let extraOptions = Cc["@mozilla.org/hash-property-bag;1"].createInstance(
|
||||
Ci.nsIWritablePropertyBag2
|
||||
);
|
||||
extraOptions.setPropertyAsBool("fromExternal", true);
|
||||
|
||||
// Always pass at least 3 arguments to avoid the "|"-splitting behavior,
|
||||
// ie. avoid the loadOneOrMoreURIs function.
|
||||
// Also, we need to pass the triggering principal.
|
||||
args = [
|
||||
urlOrUrlList,
|
||||
null, // charset
|
||||
extraOptions,
|
||||
null, // refererInfo
|
||||
postData,
|
||||
undefined, // allowThirdPartyFixup; this would be `false` but that
|
||||
|
|
|
@ -17,11 +17,13 @@ const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|||
const { AppConstants } = ChromeUtils.import(
|
||||
"resource://gre/modules/AppConstants.jsm"
|
||||
);
|
||||
const { E10SUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/E10SUtils.jsm"
|
||||
);
|
||||
|
||||
const lazy = {};
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(lazy, {
|
||||
E10SUtils: "resource://gre/modules/E10SUtils.jsm",
|
||||
LoginBreaches: "resource:///modules/LoginBreaches.jsm",
|
||||
LoginHelper: "resource://gre/modules/LoginHelper.jsm",
|
||||
LoginExport: "resource://gre/modules/LoginExport.jsm",
|
||||
|
@ -69,8 +71,7 @@ const PRIMARY_PASSWORD_NOTIFICATION_ID = "primary-password-login-required";
|
|||
|
||||
// about:logins will always use the privileged content process,
|
||||
// even if it is disabled for other consumers such as about:newtab.
|
||||
const EXPECTED_ABOUTLOGINS_REMOTE_TYPE =
|
||||
lazy.E10SUtils.PRIVILEGEDABOUT_REMOTE_TYPE;
|
||||
const EXPECTED_ABOUTLOGINS_REMOTE_TYPE = E10SUtils.PRIVILEGEDABOUT_REMOTE_TYPE;
|
||||
let _gPasswordRemaskTimeout = null;
|
||||
const convertSubjectToLogin = subject => {
|
||||
subject.QueryInterface(Ci.nsILoginMetaInfo).QueryInterface(Ci.nsILoginInfo);
|
||||
|
|
|
@ -260,7 +260,7 @@ this.windows = class extends ExtensionAPIPersistent {
|
|||
}
|
||||
}
|
||||
|
||||
args.appendElement(null); // unused
|
||||
args.appendElement(null); // extraOptions
|
||||
args.appendElement(null); // referrerInfo
|
||||
args.appendElement(null); // postData
|
||||
args.appendElement(null); // allowThirdPartyFixup
|
||||
|
|
|
@ -107,8 +107,10 @@ add_task(async function test_sessions_get_recently_closed_tabs() {
|
|||
|
||||
await extension.startup();
|
||||
|
||||
let sessionUpdatePromise = BrowserTestUtils.waitForSessionStoreUpdate(tab);
|
||||
// Test with a closed tab.
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
await sessionUpdatePromise;
|
||||
|
||||
extension.sendMessage("check-sessions");
|
||||
let recentlyClosed = await extension.awaitMessage("recentlyClosed");
|
||||
|
|
|
@ -46,6 +46,7 @@ async function openFirefoxViewTab(w = window) {
|
|||
assertFirefoxViewTab(w);
|
||||
is(w.gBrowser.tabContainer.selectedIndex, 0, "Firefox View tab is selected");
|
||||
await BrowserTestUtils.browserLoaded(w.gFirefoxViewTab.linkedBrowser);
|
||||
return w.gFirefoxViewTab;
|
||||
}
|
||||
|
||||
function closeFirefoxViewTab(w = window) {
|
||||
|
@ -121,18 +122,21 @@ add_task(async function undo_close_tab() {
|
|||
"about:about"
|
||||
);
|
||||
await TestUtils.waitForTick();
|
||||
|
||||
let sessionUpdatePromise = BrowserTestUtils.waitForSessionStoreUpdate(tab);
|
||||
gBrowser.removeTab(tab);
|
||||
await TestUtils.waitForTick();
|
||||
await sessionUpdatePromise;
|
||||
is(
|
||||
SessionStore.getClosedTabCount(window),
|
||||
1,
|
||||
"Closing about:about added to the closed tab count"
|
||||
);
|
||||
|
||||
await openFirefoxViewTab();
|
||||
let viewTab = await openFirefoxViewTab();
|
||||
await TestUtils.waitForTick();
|
||||
sessionUpdatePromise = BrowserTestUtils.waitForSessionStoreUpdate(viewTab);
|
||||
closeFirefoxViewTab();
|
||||
await TestUtils.waitForTick();
|
||||
await sessionUpdatePromise;
|
||||
is(
|
||||
SessionStore.getClosedTabCount(window),
|
||||
1,
|
||||
|
|
|
@ -26,6 +26,21 @@ async function close_tab(tab) {
|
|||
await sessionStorePromise;
|
||||
}
|
||||
|
||||
async function open_then_close(url) {
|
||||
let { updatePromise } = await BrowserTestUtils.withNewTab(
|
||||
url,
|
||||
async browser => {
|
||||
return {
|
||||
updatePromise: BrowserTestUtils.waitForSessionStoreUpdate({
|
||||
linkedBrowser: browser,
|
||||
}),
|
||||
};
|
||||
}
|
||||
);
|
||||
await updatePromise;
|
||||
return TestUtils.topicObserved("sessionstore-closed-objects-changed");
|
||||
}
|
||||
|
||||
function clearHistory() {
|
||||
Services.obs.notifyObservers(null, "browser:purge-session-history");
|
||||
}
|
||||
|
@ -86,7 +101,12 @@ add_task(async function test_empty_list() {
|
|||
});
|
||||
|
||||
add_task(async function test_list_ordering() {
|
||||
const existingData = SessionStore.getClosedTabCount(window);
|
||||
Services.obs.notifyObservers(null, "browser:purge-session-history");
|
||||
is(
|
||||
SessionStore.getClosedTabCount(window),
|
||||
0,
|
||||
"Closed tab count after purging session history"
|
||||
);
|
||||
|
||||
await BrowserTestUtils.withNewTab(
|
||||
{
|
||||
|
@ -95,9 +115,8 @@ add_task(async function test_list_ordering() {
|
|||
},
|
||||
async browser => {
|
||||
const { document } = browser.contentWindow;
|
||||
const closedObjectsChanged = TestUtils.topicObserved(
|
||||
"sessionstore-closed-objects-changed"
|
||||
);
|
||||
const closedObjectsChanged = () =>
|
||||
TestUtils.topicObserved("sessionstore-closed-objects-changed");
|
||||
|
||||
const tab1 = await add_new_tab(URLs[0]);
|
||||
const tab2 = await add_new_tab(URLs[1]);
|
||||
|
@ -106,13 +125,13 @@ add_task(async function test_list_ordering() {
|
|||
gBrowser.selectedTab = tab3;
|
||||
|
||||
await close_tab(tab3);
|
||||
await closedObjectsChanged;
|
||||
await closedObjectsChanged();
|
||||
|
||||
await close_tab(tab2);
|
||||
await closedObjectsChanged;
|
||||
await closedObjectsChanged();
|
||||
|
||||
await close_tab(tab1);
|
||||
await closedObjectsChanged;
|
||||
await closedObjectsChanged();
|
||||
|
||||
const tabsList = document.querySelector("ol.closed-tabs-list");
|
||||
await BrowserTestUtils.waitForMutationCondition(
|
||||
|
@ -121,9 +140,9 @@ add_task(async function test_list_ordering() {
|
|||
() => tabsList.children.length > 1
|
||||
);
|
||||
|
||||
ok(
|
||||
document.querySelector("ol.closed-tabs-list").children.length ===
|
||||
3 + existingData,
|
||||
is(
|
||||
document.querySelector("ol.closed-tabs-list").children.length,
|
||||
3,
|
||||
"recently-closed-tabs-list should have one list item"
|
||||
);
|
||||
|
||||
|
@ -146,8 +165,22 @@ add_task(async function test_list_ordering() {
|
|||
});
|
||||
|
||||
add_task(async function test_max_list_items() {
|
||||
// the tabs opened from the previous test provide seed data
|
||||
const mockMaxTabsLength = SessionStore.getClosedTabCount(window);
|
||||
Services.obs.notifyObservers(null, "browser:purge-session-history");
|
||||
is(
|
||||
SessionStore.getClosedTabCount(window),
|
||||
0,
|
||||
"Closed tab count after purging session history"
|
||||
);
|
||||
|
||||
await open_then_close(URLs[0]);
|
||||
await open_then_close(URLs[1]);
|
||||
await open_then_close(URLs[2]);
|
||||
|
||||
// Seed the closed tabs count. We've assured that we've opened and
|
||||
// closed at least three tabs because of the calls to open_then_close
|
||||
// above.
|
||||
let mockMaxTabsLength = 3;
|
||||
|
||||
await BrowserTestUtils.withNewTab(
|
||||
{
|
||||
gBrowser,
|
||||
|
@ -175,19 +208,12 @@ add_task(async function test_max_list_items() {
|
|||
},
|
||||
});
|
||||
|
||||
ok(
|
||||
document.querySelector("ol.closed-tabs-list").childNodes.length ===
|
||||
mockMaxTabsLength,
|
||||
is(
|
||||
document.querySelector("ol.closed-tabs-list").childNodes.length,
|
||||
mockMaxTabsLength,
|
||||
`recently-closed-tabs-list should have ${mockMaxTabsLength} list items`
|
||||
);
|
||||
|
||||
ok(
|
||||
document
|
||||
.querySelector("ol.closed-tabs-list")
|
||||
.firstChild.textContent.includes("about:firefoxview"),
|
||||
"first list item in recently-closed-tabs-list is from previous test (session store)"
|
||||
);
|
||||
|
||||
const closedObjectsChanged = TestUtils.topicObserved(
|
||||
"sessionstore-closed-objects-changed"
|
||||
);
|
||||
|
@ -203,9 +229,9 @@ add_task(async function test_max_list_items() {
|
|||
"first list item in recently-closed-tabs-list should have been updated"
|
||||
);
|
||||
|
||||
ok(
|
||||
document.querySelector("ol.closed-tabs-list").childNodes.length ===
|
||||
mockMaxTabsLength,
|
||||
is(
|
||||
document.querySelector("ol.closed-tabs-list").childNodes.length,
|
||||
mockMaxTabsLength,
|
||||
`recently-closed-tabs-list should still have ${mockMaxTabsLength} list items`
|
||||
);
|
||||
}
|
||||
|
|
|
@ -9,9 +9,12 @@ var EXPORTED_SYMBOLS = ["Qihoo360seMigrationUtils"];
|
|||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
const { MigrationUtils } = ChromeUtils.import(
|
||||
"resource:///modules/MigrationUtils.jsm"
|
||||
);
|
||||
|
||||
const lazy = {};
|
||||
XPCOMUtils.defineLazyModuleGetters(lazy, {
|
||||
MigrationUtils: "resource:///modules/MigrationUtils.jsm",
|
||||
PlacesUIUtils: "resource:///modules/PlacesUIUtils.jsm",
|
||||
PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
|
||||
Sqlite: "resource://gre/modules/Sqlite.jsm",
|
||||
|
@ -32,7 +35,7 @@ function Bookmarks(aProfileFolder) {
|
|||
this._file = file;
|
||||
}
|
||||
Bookmarks.prototype = {
|
||||
type: lazy.MigrationUtils.resourceTypes.BOOKMARKS,
|
||||
type: MigrationUtils.resourceTypes.BOOKMARKS,
|
||||
|
||||
get exists() {
|
||||
return this._file.exists() && this._file.isReadable();
|
||||
|
@ -105,10 +108,7 @@ Bookmarks.prototype = {
|
|||
|
||||
if (toolbarBMs.length) {
|
||||
let parentGuid = lazy.PlacesUtils.bookmarks.toolbarGuid;
|
||||
await lazy.MigrationUtils.insertManyBookmarksWrapper(
|
||||
toolbarBMs,
|
||||
parentGuid
|
||||
);
|
||||
await MigrationUtils.insertManyBookmarksWrapper(toolbarBMs, parentGuid);
|
||||
lazy.PlacesUIUtils.maybeToggleBookmarkToolbarVisibilityAfterMigration();
|
||||
}
|
||||
})().then(
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
|
||||
var EXPORTED_SYMBOLS = ["ChromeMacOSLoginCrypto"];
|
||||
|
||||
Cu.importGlobalProperties(["crypto"]);
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
|
|
|
@ -19,10 +19,13 @@ const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|||
const { AppConstants } = ChromeUtils.import(
|
||||
"resource://gre/modules/AppConstants.jsm"
|
||||
);
|
||||
const { MigratorPrototype } = ChromeUtils.import(
|
||||
"resource:///modules/MigrationUtils.jsm"
|
||||
);
|
||||
|
||||
const lazy = {};
|
||||
XPCOMUtils.defineLazyModuleGetters(lazy, {
|
||||
ChromeMigrationUtils: "resource:///modules/ChromeMigrationUtils.jsm",
|
||||
MigratorPrototype: "resource:///modules/MigrationUtils.jsm",
|
||||
MigrationUtils: "resource:///modules/MigrationUtils.jsm",
|
||||
NetUtil: "resource://gre/modules/NetUtil.jsm",
|
||||
OS: "resource://gre/modules/osfile.jsm",
|
||||
|
@ -76,7 +79,7 @@ function ChromeProfileMigrator() {
|
|||
this._chromeUserDataPathSuffix = "Chrome";
|
||||
}
|
||||
|
||||
ChromeProfileMigrator.prototype = Object.create(lazy.MigratorPrototype);
|
||||
ChromeProfileMigrator.prototype = Object.create(MigratorPrototype);
|
||||
|
||||
ChromeProfileMigrator.prototype._keychainServiceName = "Chrome Safe Storage";
|
||||
ChromeProfileMigrator.prototype._keychainAccountName = "Chrome";
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
|
||||
var EXPORTED_SYMBOLS = ["ChromeWindowsLoginCrypto"];
|
||||
|
||||
Cu.importGlobalProperties(["atob", "crypto"]);
|
||||
|
||||
const { ChromeMigrationUtils } = ChromeUtils.import(
|
||||
"resource:///modules/ChromeMigrationUtils.jsm"
|
||||
);
|
||||
|
|
|
@ -31,11 +31,7 @@ ChromeUtils.defineModuleGetter(
|
|||
"WindowsRegistry",
|
||||
"resource://gre/modules/WindowsRegistry.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
lazy,
|
||||
"ctypes",
|
||||
"resource://gre/modules/ctypes.jsm"
|
||||
);
|
||||
const { ctypes } = ChromeUtils.import("resource://gre/modules/ctypes.jsm");
|
||||
|
||||
const EDGE_COOKIE_PATH_OPTIONS = ["", "#!001\\", "#!002\\"];
|
||||
const EDGE_COOKIES_SUFFIX = "MicrosoftEdge\\Cookies";
|
||||
|
@ -57,15 +53,15 @@ const WEB_CREDENTIALS_VAULT_ID = [
|
|||
];
|
||||
|
||||
const wintypes = {
|
||||
BOOL: lazy.ctypes.int,
|
||||
DWORD: lazy.ctypes.uint32_t,
|
||||
DWORDLONG: lazy.ctypes.uint64_t,
|
||||
CHAR: lazy.ctypes.char,
|
||||
PCHAR: lazy.ctypes.char.ptr,
|
||||
LPCWSTR: lazy.ctypes.char16_t.ptr,
|
||||
PDWORD: lazy.ctypes.uint32_t.ptr,
|
||||
VOIDP: lazy.ctypes.voidptr_t,
|
||||
WORD: lazy.ctypes.uint16_t,
|
||||
BOOL: ctypes.int,
|
||||
DWORD: ctypes.uint32_t,
|
||||
DWORDLONG: ctypes.uint64_t,
|
||||
CHAR: ctypes.char,
|
||||
PCHAR: ctypes.char.ptr,
|
||||
LPCWSTR: ctypes.char16_t.ptr,
|
||||
PDWORD: ctypes.uint32_t.ptr,
|
||||
VOIDP: ctypes.voidptr_t,
|
||||
WORD: ctypes.uint16_t,
|
||||
};
|
||||
|
||||
// TODO: Bug 1202978 - Refactor MSMigrationUtils ctypes helpers
|
||||
|
@ -74,7 +70,7 @@ function CtypesKernelHelpers() {
|
|||
this._functions = {};
|
||||
this._libs = {};
|
||||
|
||||
this._structs.SYSTEMTIME = new lazy.ctypes.StructType("SYSTEMTIME", [
|
||||
this._structs.SYSTEMTIME = new ctypes.StructType("SYSTEMTIME", [
|
||||
{ wYear: wintypes.WORD },
|
||||
{ wMonth: wintypes.WORD },
|
||||
{ wDayOfWeek: wintypes.WORD },
|
||||
|
@ -85,17 +81,17 @@ function CtypesKernelHelpers() {
|
|||
{ wMilliseconds: wintypes.WORD },
|
||||
]);
|
||||
|
||||
this._structs.FILETIME = new lazy.ctypes.StructType("FILETIME", [
|
||||
this._structs.FILETIME = new ctypes.StructType("FILETIME", [
|
||||
{ dwLowDateTime: wintypes.DWORD },
|
||||
{ dwHighDateTime: wintypes.DWORD },
|
||||
]);
|
||||
|
||||
try {
|
||||
this._libs.kernel32 = lazy.ctypes.open("Kernel32");
|
||||
this._libs.kernel32 = ctypes.open("Kernel32");
|
||||
|
||||
this._functions.FileTimeToSystemTime = this._libs.kernel32.declare(
|
||||
"FileTimeToSystemTime",
|
||||
lazy.ctypes.winapi_abi,
|
||||
ctypes.winapi_abi,
|
||||
wintypes.BOOL,
|
||||
this._structs.FILETIME.ptr,
|
||||
this._structs.SYSTEMTIME.ptr
|
||||
|
@ -142,7 +138,7 @@ CtypesKernelHelpers.prototype = {
|
|||
systemTime.address()
|
||||
);
|
||||
if (result == 0) {
|
||||
throw new Error(lazy.ctypes.winLastError);
|
||||
throw new Error(ctypes.winLastError);
|
||||
}
|
||||
|
||||
// System time is in UTC, so we use Date.UTC to get milliseconds from epoch,
|
||||
|
@ -165,11 +161,11 @@ function CtypesVaultHelpers() {
|
|||
this._structs = {};
|
||||
this._functions = {};
|
||||
|
||||
this._structs.GUID = new lazy.ctypes.StructType("GUID", [
|
||||
this._structs.GUID = new ctypes.StructType("GUID", [
|
||||
{ id: wintypes.DWORD.array(4) },
|
||||
]);
|
||||
|
||||
this._structs.VAULT_ITEM_ELEMENT = new lazy.ctypes.StructType(
|
||||
this._structs.VAULT_ITEM_ELEMENT = new ctypes.StructType(
|
||||
"VAULT_ITEM_ELEMENT",
|
||||
[
|
||||
// not documented
|
||||
|
@ -187,7 +183,7 @@ function CtypesVaultHelpers() {
|
|||
]
|
||||
);
|
||||
|
||||
this._structs.VAULT_ELEMENT = new lazy.ctypes.StructType("VAULT_ELEMENT", [
|
||||
this._structs.VAULT_ELEMENT = new ctypes.StructType("VAULT_ELEMENT", [
|
||||
// vault item schemaId
|
||||
{ schemaId: this._structs.GUID },
|
||||
// a pointer to the name of the browser VAULT_ITEM_ELEMENT
|
||||
|
@ -212,11 +208,11 @@ function CtypesVaultHelpers() {
|
|||
]);
|
||||
|
||||
try {
|
||||
this._vaultcliLib = lazy.ctypes.open("vaultcli.dll");
|
||||
this._vaultcliLib = ctypes.open("vaultcli.dll");
|
||||
|
||||
this._functions.VaultOpenVault = this._vaultcliLib.declare(
|
||||
"VaultOpenVault",
|
||||
lazy.ctypes.winapi_abi,
|
||||
ctypes.winapi_abi,
|
||||
wintypes.DWORD,
|
||||
// GUID
|
||||
this._structs.GUID.ptr,
|
||||
|
@ -227,7 +223,7 @@ function CtypesVaultHelpers() {
|
|||
);
|
||||
this._functions.VaultEnumerateItems = this._vaultcliLib.declare(
|
||||
"VaultEnumerateItems",
|
||||
lazy.ctypes.winapi_abi,
|
||||
ctypes.winapi_abi,
|
||||
wintypes.DWORD,
|
||||
// Vault Handle
|
||||
wintypes.VOIDP,
|
||||
|
@ -236,18 +232,18 @@ function CtypesVaultHelpers() {
|
|||
// Items Count
|
||||
wintypes.PDWORD,
|
||||
// Items
|
||||
lazy.ctypes.voidptr_t
|
||||
ctypes.voidptr_t
|
||||
);
|
||||
this._functions.VaultCloseVault = this._vaultcliLib.declare(
|
||||
"VaultCloseVault",
|
||||
lazy.ctypes.winapi_abi,
|
||||
ctypes.winapi_abi,
|
||||
wintypes.DWORD,
|
||||
// Vault Handle
|
||||
wintypes.VOIDP
|
||||
);
|
||||
this._functions.VaultGetItem = this._vaultcliLib.declare(
|
||||
"VaultGetItem",
|
||||
lazy.ctypes.winapi_abi,
|
||||
ctypes.winapi_abi,
|
||||
wintypes.DWORD,
|
||||
// Vault Handle
|
||||
wintypes.VOIDP,
|
||||
|
@ -268,7 +264,7 @@ function CtypesVaultHelpers() {
|
|||
);
|
||||
this._functions.VaultFree = this._vaultcliLib.declare(
|
||||
"VaultFree",
|
||||
lazy.ctypes.winapi_abi,
|
||||
ctypes.winapi_abi,
|
||||
wintypes.DWORD,
|
||||
// Memory
|
||||
this._structs.VAULT_ELEMENT.ptr
|
||||
|
|
|
@ -12,7 +12,6 @@ const { AppConstants } = ChromeUtils.import(
|
|||
"resource://gre/modules/AppConstants.jsm"
|
||||
);
|
||||
const lazy = {};
|
||||
XPCOMUtils.defineLazyGlobalGetters(lazy, ["fetch"]);
|
||||
XPCOMUtils.defineLazyModuleGetters(lazy, {
|
||||
SnippetsTestMessageProvider:
|
||||
"resource://activity-stream/lib/SnippetsTestMessageProvider.jsm",
|
||||
|
@ -192,7 +191,7 @@ const MessageLoaderUtils = {
|
|||
|
||||
let response;
|
||||
try {
|
||||
response = await lazy.fetch(provider.url, {
|
||||
response = await fetch(provider.url, {
|
||||
headers,
|
||||
credentials: "omit",
|
||||
});
|
||||
|
|
|
@ -13,6 +13,12 @@ const { XPCOMUtils } = ChromeUtils.import(
|
|||
const { AppConstants } = ChromeUtils.import(
|
||||
"resource://gre/modules/AppConstants.jsm"
|
||||
);
|
||||
const { NewTabUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/NewTabUtils.jsm"
|
||||
);
|
||||
const { ShellService } = ChromeUtils.import(
|
||||
"resource:///modules/ShellService.jsm"
|
||||
);
|
||||
|
||||
const lazy = {};
|
||||
|
||||
|
@ -20,9 +26,7 @@ XPCOMUtils.defineLazyModuleGetters(lazy, {
|
|||
ASRouterPreferences: "resource://activity-stream/lib/ASRouterPreferences.jsm",
|
||||
AddonManager: "resource://gre/modules/AddonManager.jsm",
|
||||
ClientEnvironment: "resource://normandy/lib/ClientEnvironment.jsm",
|
||||
NewTabUtils: "resource://gre/modules/NewTabUtils.jsm",
|
||||
ProfileAge: "resource://gre/modules/ProfileAge.jsm",
|
||||
ShellService: "resource:///modules/ShellService.jsm",
|
||||
TelemetryEnvironment: "resource://gre/modules/TelemetryEnvironment.jsm",
|
||||
AttributionCode: "resource:///modules/AttributionCode.jsm",
|
||||
TargetingContext: "resource://messaging-system/targeting/Targeting.jsm",
|
||||
|
@ -116,7 +120,7 @@ XPCOMUtils.defineLazyServiceGetters(lazy, {
|
|||
|
||||
const FXA_USERNAME_PREF = "services.sync.username";
|
||||
|
||||
const { activityStreamProvider: asProvider } = lazy.NewTabUtils;
|
||||
const { activityStreamProvider: asProvider } = NewTabUtils;
|
||||
|
||||
const FXA_ATTACHED_CLIENTS_UPDATE_INTERVAL = 4 * 60 * 60 * 1000; // Four hours
|
||||
const FRECENT_SITES_UPDATE_INTERVAL = 6 * 60 * 60 * 1000; // Six hours
|
||||
|
@ -265,7 +269,7 @@ const QueryCache = {
|
|||
"doesAppNeedPin",
|
||||
null,
|
||||
FRECENT_SITES_UPDATE_INTERVAL,
|
||||
lazy.ShellService
|
||||
ShellService
|
||||
),
|
||||
},
|
||||
};
|
||||
|
@ -477,7 +481,7 @@ const TargetingGetters = {
|
|||
},
|
||||
get isDefaultBrowser() {
|
||||
try {
|
||||
return lazy.ShellService.isDefaultBrowser();
|
||||
return ShellService.isDefaultBrowser();
|
||||
} catch (e) {}
|
||||
return null;
|
||||
},
|
||||
|
@ -498,7 +502,7 @@ const TargetingGetters = {
|
|||
return QueryCache.queries.RecentBookmarks.get();
|
||||
},
|
||||
get pinnedSites() {
|
||||
return lazy.NewTabUtils.pinnedLinks.links.map(site =>
|
||||
return NewTabUtils.pinnedLinks.links.map(site =>
|
||||
site
|
||||
? {
|
||||
url: site.url,
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
const lazy = {};
|
||||
/* 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/. */
|
||||
|
||||
const lazy = {};
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
lazy,
|
||||
"IndexedDB",
|
||||
|
|
|
@ -10,8 +10,6 @@ const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|||
|
||||
const lazy = {};
|
||||
|
||||
XPCOMUtils.defineLazyGlobalGetters(lazy, ["fetch"]);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(lazy, {
|
||||
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
|
||||
RemoteL10n: "resource://activity-stream/lib/RemoteL10n.jsm",
|
||||
|
@ -881,7 +879,7 @@ const CFRPageActions = {
|
|||
async _fetchLatestAddonVersion(id) {
|
||||
let url = null;
|
||||
try {
|
||||
const response = await lazy.fetch(`${ADDONS_API_URL}/${id}/`, {
|
||||
const response = await fetch(`${ADDONS_API_URL}/${id}/`, {
|
||||
credentials: "omit",
|
||||
});
|
||||
if (response.status !== 204 && response.ok) {
|
||||
|
|
|
@ -3,9 +3,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
const lazy = {};
|
||||
ChromeUtils.defineModuleGetter(
|
||||
lazy,
|
||||
|
@ -21,7 +18,6 @@ const { setTimeout, clearTimeout } = ChromeUtils.import(
|
|||
"resource://gre/modules/Timer.jsm"
|
||||
);
|
||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
XPCOMUtils.defineLazyGlobalGetters(lazy, ["fetch"]);
|
||||
const { actionTypes: at, actionCreators: ac } = ChromeUtils.import(
|
||||
"resource://activity-stream/common/Actions.jsm"
|
||||
);
|
||||
|
@ -287,7 +283,7 @@ class DiscoveryStreamFeed {
|
|||
const controller = new AbortController();
|
||||
const { signal } = controller;
|
||||
|
||||
const fetchPromise = lazy.fetch(endpoint, {
|
||||
const fetchPromise = fetch(endpoint, {
|
||||
...options,
|
||||
credentials: "omit",
|
||||
signal,
|
||||
|
|
|
@ -18,11 +18,6 @@ ChromeUtils.defineModuleGetter(
|
|||
);
|
||||
|
||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyGlobalGetters(lazy, ["fetch"]);
|
||||
|
||||
const { BasePromiseWorker } = ChromeUtils.import(
|
||||
"resource://gre/modules/PromiseWorker.jsm"
|
||||
|
@ -67,7 +62,7 @@ class PersonalityProvider {
|
|||
}
|
||||
const server = Services.prefs.getCharPref("services.settings.server");
|
||||
const serverInfo = await (
|
||||
await lazy.fetch(`${server}/`, {
|
||||
await fetch(`${server}/`, {
|
||||
credentials: "omit",
|
||||
})
|
||||
).json();
|
||||
|
|
|
@ -135,80 +135,95 @@ class _RemoteImages {
|
|||
* then the promise will resolve to null.
|
||||
*/
|
||||
async patchMessage(message, replaceWith = "imageURL") {
|
||||
try {
|
||||
if (!!message && !!message.imageId) {
|
||||
const { imageId } = message;
|
||||
const blobURL = await this.load(imageId);
|
||||
if (!!message && !!message.imageId) {
|
||||
const { imageId } = message;
|
||||
const urls = await this.load(imageId);
|
||||
|
||||
if (urls.size) {
|
||||
const blobURL = urls.get(imageId);
|
||||
|
||||
delete message.imageId;
|
||||
|
||||
message[replaceWith] = blobURL;
|
||||
|
||||
return () => this.unload(blobURL);
|
||||
return () => this.unload(urls);
|
||||
}
|
||||
return null;
|
||||
} catch (e) {
|
||||
Cu.reportError(
|
||||
`RemoteImages Could not patch message with imageId "${message.imageId}": ${e}`
|
||||
);
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a remote image.
|
||||
* Load remote images.
|
||||
*
|
||||
* If the image has not been previously downloaded then the image will be
|
||||
* If the images have not been previously downloaded, then they will be
|
||||
* downloaded from RemoteSettings.
|
||||
*
|
||||
* @param imageId The unique image ID.
|
||||
* @param {...string} imageIds The image IDs to load.
|
||||
*
|
||||
* @throws This method throws if the image cannot be loaded.
|
||||
* @returns {object} An object mapping image Ids to blob: URLs.
|
||||
* If an image could not be loaded, it will not be present
|
||||
* in the returned object.
|
||||
*
|
||||
* @returns A promise that resolves with a blob URL for the given image, or
|
||||
* rejects with an error.
|
||||
*
|
||||
* After the caller is finished with the image, they must call
|
||||
* |RemoteImages.unload()| on the returned URL.
|
||||
* After the caller is finished with the images, they must call
|
||||
* |RemoteImages.unload()| on the object.
|
||||
*/
|
||||
load(imageId) {
|
||||
load(...imageIds) {
|
||||
return this.withDb(async db => {
|
||||
const recordId = this.#getRecordId(imageId);
|
||||
// Deduplicate repeated imageIds by using a Map.
|
||||
const urls = new Map(imageIds.map(key => [key, undefined]));
|
||||
|
||||
let blob;
|
||||
if (db.data.images[recordId]) {
|
||||
// We have previously fetched this image, we can load it from disk.
|
||||
try {
|
||||
blob = await this.#readFromDisk(db, recordId);
|
||||
} catch (e) {
|
||||
if (
|
||||
!(
|
||||
e instanceof Components.Exception &&
|
||||
e.name === "NS_ERROR_FILE_NOT_FOUND"
|
||||
)
|
||||
) {
|
||||
throw e;
|
||||
await Promise.all(
|
||||
Array.from(urls.keys()).map(async imageId => {
|
||||
try {
|
||||
urls.set(imageId, await this.#loadImpl(db, imageId));
|
||||
} catch (e) {
|
||||
Cu.reportError(`Could not load image ID ${imageId}: ${e}`);
|
||||
urls.delete(imageId);
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// Fall back to downloading if we cannot read it from disk.
|
||||
}
|
||||
|
||||
if (typeof blob === "undefined") {
|
||||
blob = await this.#download(db, recordId);
|
||||
}
|
||||
|
||||
return URL.createObjectURL(blob);
|
||||
return urls;
|
||||
});
|
||||
}
|
||||
|
||||
async #loadImpl(db, imageId) {
|
||||
const recordId = this.#getRecordId(imageId);
|
||||
|
||||
let blob;
|
||||
if (db.data.images[recordId]) {
|
||||
// We have previously fetched this image, we can load it from disk.
|
||||
try {
|
||||
blob = await this.#readFromDisk(db, recordId);
|
||||
} catch (e) {
|
||||
if (
|
||||
!(
|
||||
e instanceof Components.Exception &&
|
||||
e.name === "NS_ERROR_FILE_NOT_FOUND"
|
||||
)
|
||||
) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to downloading if we cannot read it from disk.
|
||||
}
|
||||
|
||||
if (typeof blob === "undefined") {
|
||||
blob = await this.#download(db, recordId);
|
||||
}
|
||||
|
||||
return URL.createObjectURL(blob);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unload a URL returned by RemoteImages
|
||||
* Unload URLs returned by RemoteImages
|
||||
*
|
||||
* @param url The URL to unload.
|
||||
* @param {Map<string, string>} urls The result of calling |RemoteImages.load()|.
|
||||
**/
|
||||
unload(url) {
|
||||
URL.revokeObjectURL(url);
|
||||
unload(urls) {
|
||||
for (const url of urls.keys()) {
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -11,8 +11,6 @@ const { XPCOMUtils } = ChromeUtils.import(
|
|||
|
||||
const lazy = {};
|
||||
|
||||
XPCOMUtils.defineLazyGlobalGetters(lazy, ["fetch"]);
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
lazy,
|
||||
"BackgroundPageThumbs",
|
||||
|
@ -63,7 +61,7 @@ const Screenshots = {
|
|||
// Blob URIs for the screenshots.
|
||||
const imgPath = lazy.PageThumbs.getThumbnailPath(url);
|
||||
|
||||
const filePathResponse = await lazy.fetch(`file://${imgPath}`);
|
||||
const filePathResponse = await fetch(`file://${imgPath}`);
|
||||
const fileContents = await filePathResponse.blob();
|
||||
|
||||
// Check if the file is empty, which indicates there isn't actually a
|
||||
|
|
|
@ -2,15 +2,8 @@
|
|||
* 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/. */
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const lazy = {};
|
||||
|
||||
XPCOMUtils.defineLazyGlobalGetters(lazy, ["fetch"]);
|
||||
|
||||
const TIPPYTOP_PATH = "chrome://activity-stream/content/data/content/tippytop/";
|
||||
const TIPPYTOP_JSON_PATH =
|
||||
"chrome://activity-stream/content/data/content/tippytop/top_sites.json";
|
||||
|
@ -43,7 +36,7 @@ class TippyTopProvider {
|
|||
// Load the Tippy Top sites from the json manifest.
|
||||
try {
|
||||
for (const site of await (
|
||||
await lazy.fetch(TIPPYTOP_JSON_PATH, {
|
||||
await fetch(TIPPYTOP_JSON_PATH, {
|
||||
credentials: "omit",
|
||||
})
|
||||
).json()) {
|
||||
|
|
|
@ -74,8 +74,6 @@ ChromeUtils.defineModuleGetter(
|
|||
"resource://gre/modules/Region.jsm"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyGlobalGetters(lazy, ["fetch"]);
|
||||
|
||||
XPCOMUtils.defineLazyGetter(lazy, "log", () => {
|
||||
const { Logger } = ChromeUtils.import(
|
||||
"resource://messaging-system/lib/Logger.jsm"
|
||||
|
@ -186,7 +184,7 @@ class ContileIntegration {
|
|||
}
|
||||
try {
|
||||
let url = Services.prefs.getStringPref(CONTILE_ENDPOINT_PREF);
|
||||
const response = await lazy.fetch(url, { credentials: "omit" });
|
||||
const response = await fetch(url, { credentials: "omit" });
|
||||
if (!response.ok) {
|
||||
lazy.log.warn(
|
||||
`Contile endpoint returned unexpected status: ${response.status}`
|
||||
|
|
|
@ -3,15 +3,10 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
const { NewTabUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/NewTabUtils.jsm"
|
||||
);
|
||||
const lazy = {};
|
||||
XPCOMUtils.defineLazyGlobalGetters(lazy, ["fetch"]);
|
||||
|
||||
const { actionTypes: at, actionCreators: ac } = ChromeUtils.import(
|
||||
"resource://activity-stream/common/Actions.jsm"
|
||||
|
@ -29,6 +24,7 @@ const { PersistentCache } = ChromeUtils.import(
|
|||
"resource://activity-stream/lib/PersistentCache.jsm"
|
||||
);
|
||||
|
||||
const lazy = {};
|
||||
ChromeUtils.defineModuleGetter(
|
||||
lazy,
|
||||
"pktApi",
|
||||
|
@ -196,7 +192,7 @@ class TopStoriesFeed {
|
|||
return null;
|
||||
}
|
||||
try {
|
||||
const response = await lazy.fetch(this.stories_endpoint, {
|
||||
const response = await fetch(this.stories_endpoint, {
|
||||
credentials: "omit",
|
||||
});
|
||||
if (!response.ok) {
|
||||
|
@ -296,7 +292,7 @@ class TopStoriesFeed {
|
|||
return null;
|
||||
}
|
||||
try {
|
||||
const response = await lazy.fetch(this.topics_endpoint, {
|
||||
const response = await fetch(this.topics_endpoint, {
|
||||
credentials: "omit",
|
||||
});
|
||||
if (!response.ok) {
|
||||
|
|
|
@ -14,8 +14,6 @@ const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|||
|
||||
const RS_SERVER_PREF = "services.settings.server";
|
||||
|
||||
Cu.importGlobalProperties(["fetch"]);
|
||||
|
||||
const RemoteImagesTestUtils = {
|
||||
/**
|
||||
* Serve a mock Remote Settings server with content for Remote Images
|
||||
|
@ -26,70 +24,72 @@ const RemoteImagesTestUtils = {
|
|||
* @returns A promise yielding a cleanup function. This function will stop the
|
||||
* internal HTTP server and clean up all Remote Images state.
|
||||
*/
|
||||
async serveRemoteImages(imageInfo) {
|
||||
const { filename, recordId, mimetype, hash, url, size } = imageInfo;
|
||||
|
||||
async serveRemoteImages(...imageInfos) {
|
||||
const server = new HttpServer();
|
||||
server.start(-1);
|
||||
|
||||
const baseURL = `http://localhost:${server.identity.primaryPort}/`;
|
||||
|
||||
const arrayBuffer = await fetch(url, { credentials: "omit" }).then(rsp =>
|
||||
rsp.arrayBuffer()
|
||||
);
|
||||
for (const imageInfo of imageInfos) {
|
||||
const { filename, recordId, mimetype, hash, url, size } = imageInfo;
|
||||
|
||||
server.registerPathHandler("/v1/", (request, response) => {
|
||||
response.write(
|
||||
JSON.stringify({
|
||||
capabilities: {
|
||||
attachments: {
|
||||
base_url: `${baseURL}cdn`,
|
||||
},
|
||||
},
|
||||
})
|
||||
const arrayBuffer = await fetch(url, { credentials: "omit" }).then(rsp =>
|
||||
rsp.arrayBuffer()
|
||||
);
|
||||
|
||||
response.setHeader("Content-Type", "application/json; charset=UTF-8");
|
||||
response.setStatusLine(null, 200, "OK");
|
||||
});
|
||||
|
||||
server.registerPathHandler(
|
||||
`/v1/buckets/main/collections/ms-images/records/${recordId}`,
|
||||
(request, response) => {
|
||||
server.registerPathHandler("/v1/", (request, response) => {
|
||||
response.write(
|
||||
JSON.stringify({
|
||||
data: {
|
||||
attachment: {
|
||||
filename,
|
||||
location: `main/ms-images/${recordId}`,
|
||||
hash,
|
||||
mimetype,
|
||||
size,
|
||||
capabilities: {
|
||||
attachments: {
|
||||
base_url: `${baseURL}cdn`,
|
||||
},
|
||||
},
|
||||
id: "image-id",
|
||||
last_modified: Date.now(),
|
||||
})
|
||||
);
|
||||
|
||||
response.setHeader("Content-Type", "application/json; charset=UTF-8");
|
||||
response.setStatusLine(null, 200, "OK");
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
server.registerPathHandler(
|
||||
`/cdn/main/ms-images/${recordId}`,
|
||||
async (request, response) => {
|
||||
const stream = Cc[
|
||||
"@mozilla.org/io/arraybuffer-input-stream;1"
|
||||
].createInstance(Ci.nsIArrayBufferInputStream);
|
||||
stream.setData(arrayBuffer, 0, arrayBuffer.byteLength);
|
||||
server.registerPathHandler(
|
||||
`/v1/buckets/main/collections/ms-images/records/${recordId}`,
|
||||
(request, response) => {
|
||||
response.write(
|
||||
JSON.stringify({
|
||||
data: {
|
||||
attachment: {
|
||||
filename,
|
||||
location: `main/ms-images/${recordId}`,
|
||||
hash,
|
||||
mimetype,
|
||||
size,
|
||||
},
|
||||
},
|
||||
id: "image-id",
|
||||
last_modified: Date.now(),
|
||||
})
|
||||
);
|
||||
|
||||
response.bodyOutputStream.writeFrom(stream, size);
|
||||
response.setHeader("Content-Type", mimetype);
|
||||
response.setStatusLine(null, 200, "OK");
|
||||
}
|
||||
);
|
||||
response.setHeader("Content-Type", "application/json; charset=UTF-8");
|
||||
response.setStatusLine(null, 200, "OK");
|
||||
}
|
||||
);
|
||||
|
||||
server.registerPathHandler(
|
||||
`/cdn/main/ms-images/${recordId}`,
|
||||
async (request, response) => {
|
||||
const stream = Cc[
|
||||
"@mozilla.org/io/arraybuffer-input-stream;1"
|
||||
].createInstance(Ci.nsIArrayBufferInputStream);
|
||||
stream.setData(arrayBuffer, 0, arrayBuffer.byteLength);
|
||||
|
||||
response.bodyOutputStream.writeFrom(stream, size);
|
||||
response.setHeader("Content-Type", mimetype);
|
||||
response.setStatusLine(null, 200, "OK");
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
Services.prefs.setCharPref(RS_SERVER_PREF, `${baseURL}v1`);
|
||||
|
||||
|
@ -177,6 +177,16 @@ const RemoteImagesTestUtils = {
|
|||
url: "chrome://browser/content/aboutRobots-icon.png",
|
||||
size: 7599,
|
||||
},
|
||||
|
||||
Mountain: {
|
||||
filename: "mountain.svg",
|
||||
recordId: "mountain",
|
||||
mimetype: "image/svg+xml",
|
||||
hash: "96902f3d784e1b5e49547c543a5c121442c64b180deb2c38246fada1d14597ac",
|
||||
url:
|
||||
"chrome://activity-stream/content/data/content/assets/remote/mountain.svg",
|
||||
size: 1650,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
const { BrowserTestUtils } = ChromeUtils.import(
|
||||
"resource://testing-common/BrowserTestUtils.jsm"
|
||||
);
|
||||
const { Downloader } = ChromeUtils.import(
|
||||
"resource://services-settings/Attachments.jsm"
|
||||
);
|
||||
const {
|
||||
RemoteImages,
|
||||
REMOTE_IMAGES_PATH,
|
||||
|
@ -24,21 +27,16 @@ function dbWriteFinished(db) {
|
|||
add_setup(RemoteImagesTestUtils.wipeCache);
|
||||
|
||||
add_task(async function test_remoteImages_load() {
|
||||
registerCleanupFunction(RemoteImagesTestUtils.wipeCache);
|
||||
|
||||
const imageInfo = RemoteImagesTestUtils.images.AboutRobots;
|
||||
|
||||
registerCleanupFunction(
|
||||
await RemoteImagesTestUtils.serveRemoteImages(imageInfo)
|
||||
);
|
||||
async function runLoadTest(recordId, imageId) {
|
||||
const urls = await RemoteImages.load(imageId);
|
||||
Assert.equal(urls.size, 1, "RemogeImages.load() returns one result");
|
||||
|
||||
async function runLoadTest(imageId) {
|
||||
const url = await RemoteImages.load(imageId);
|
||||
const url = urls.get(imageId);
|
||||
Assert.ok(url.startsWith("blob:"), "RemoteImages.load() returns blob URL");
|
||||
Assert.ok(
|
||||
await IOUtils.exists(
|
||||
PathUtils.join(REMOTE_IMAGES_PATH, imageInfo.recordId)
|
||||
),
|
||||
await IOUtils.exists(PathUtils.join(REMOTE_IMAGES_PATH, recordId)),
|
||||
"RemoteImages caches the image"
|
||||
);
|
||||
|
||||
|
@ -62,19 +60,26 @@ add_task(async function test_remoteImages_load() {
|
|||
"Data read from blob: URL matches expected"
|
||||
);
|
||||
|
||||
RemoteImages.unload(url);
|
||||
RemoteImages.unload(urls);
|
||||
}
|
||||
|
||||
info("Loading a RemoteImage with a record ID");
|
||||
await runLoadTest(imageInfo.recordId);
|
||||
const stop = await RemoteImagesTestUtils.serveRemoteImages(imageInfo);
|
||||
|
||||
info("Loading a RemoteImage with a legacy image ID (record ID + extension)");
|
||||
await runLoadTest(`${imageInfo.recordId}.png`);
|
||||
try {
|
||||
info("Loading a RemoteImage with a record ID");
|
||||
await runLoadTest(imageInfo.recordId, imageInfo.recordId);
|
||||
|
||||
info(
|
||||
"Loading a RemoteImage with a legacy image ID (record ID + extension)"
|
||||
);
|
||||
await runLoadTest(imageInfo.recordId, `${imageInfo.recordId}.png`);
|
||||
} finally {
|
||||
await stop();
|
||||
await RemoteImagesTestUtils.wipeCache();
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function test_remoteImages_load_fallback() {
|
||||
registerCleanupFunction(RemoteImagesTestUtils.wipeCache);
|
||||
|
||||
const imageInfo = RemoteImagesTestUtils.images.AboutRobots;
|
||||
const origDbContent = {
|
||||
version: 1,
|
||||
|
@ -85,99 +90,138 @@ add_task(async function test_remoteImages_load_fallback() {
|
|||
|
||||
await IOUtils.writeJSON(REMOTE_IMAGES_DB_PATH, origDbContent);
|
||||
|
||||
registerCleanupFunction(
|
||||
await RemoteImagesTestUtils.serveRemoteImages(imageInfo)
|
||||
);
|
||||
const stop = await RemoteImagesTestUtils.serveRemoteImages(imageInfo);
|
||||
|
||||
const url = await RemoteImages.load(imageInfo.recordId);
|
||||
RemoteImages.unload(url);
|
||||
try {
|
||||
const urls = await RemoteImages.load(imageInfo.recordId);
|
||||
RemoteImages.unload(urls);
|
||||
|
||||
await RemoteImages.withDb(async db => {
|
||||
Assert.ok(
|
||||
imageInfo.recordId in db.data.images,
|
||||
"RemoteImages DB entry present"
|
||||
);
|
||||
await RemoteImages.withDb(async db => {
|
||||
Assert.ok(
|
||||
imageInfo.recordId in db.data.images,
|
||||
"RemoteImages DB entry present"
|
||||
);
|
||||
|
||||
Assert.notDeepEqual(
|
||||
db.data,
|
||||
origDbContent,
|
||||
"RemoteImages DB changed after load()"
|
||||
);
|
||||
Assert.notDeepEqual(
|
||||
db.data,
|
||||
origDbContent,
|
||||
"RemoteImages DB changed after load()"
|
||||
);
|
||||
|
||||
await dbWriteFinished(db);
|
||||
await dbWriteFinished(db);
|
||||
|
||||
const onDisk = await IOUtils.readJSON(REMOTE_IMAGES_DB_PATH);
|
||||
Assert.deepEqual(
|
||||
db.data,
|
||||
onDisk,
|
||||
"RemoteImages DB was saved to disk after load() falled back to download"
|
||||
);
|
||||
});
|
||||
const onDisk = await IOUtils.readJSON(REMOTE_IMAGES_DB_PATH);
|
||||
Assert.deepEqual(
|
||||
db.data,
|
||||
onDisk,
|
||||
"RemoteImages DB was saved to disk after load() falled back to download"
|
||||
);
|
||||
});
|
||||
} finally {
|
||||
await stop();
|
||||
await RemoteImagesTestUtils.wipeCache();
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function test_remoteImages_expire() {
|
||||
registerCleanupFunction(RemoteImagesTestUtils.wipeCache);
|
||||
|
||||
const THIRTY_ONE_DAYS = 31 * 24 * 60 * 60;
|
||||
const IMAGE_INFO = RemoteImagesTestUtils.images.AboutRobots;
|
||||
|
||||
await RemoteImages.reset();
|
||||
try {
|
||||
await RemoteImagesTestUtils.writeImage(IMAGE_INFO);
|
||||
await IOUtils.writeJSON(REMOTE_IMAGES_DB_PATH, {
|
||||
version: 1,
|
||||
images: {
|
||||
...RemoteImagesTestUtils.dbEntryFor(
|
||||
IMAGE_INFO,
|
||||
Date.now() - THIRTY_ONE_DAYS
|
||||
),
|
||||
},
|
||||
});
|
||||
|
||||
await RemoteImagesTestUtils.writeImage(IMAGE_INFO);
|
||||
await IOUtils.writeJSON(REMOTE_IMAGES_DB_PATH, {
|
||||
version: 1,
|
||||
images: {
|
||||
...RemoteImagesTestUtils.dbEntryFor(
|
||||
IMAGE_INFO,
|
||||
Date.now() - THIRTY_ONE_DAYS
|
||||
),
|
||||
},
|
||||
});
|
||||
|
||||
await RemoteImagesTestUtils.triggerCleanup();
|
||||
await RemoteImages.withDb(async db => {
|
||||
Assert.deepEqual(db.data.images, [], "RemoteImages should have no images");
|
||||
Assert.ok(
|
||||
!(await IOUtils.exists(
|
||||
PathUtils.join(REMOTE_IMAGES_PATH, IMAGE_INFO.recordId)
|
||||
)),
|
||||
"Image should have been deleted during cleanup"
|
||||
);
|
||||
});
|
||||
await RemoteImagesTestUtils.triggerCleanup();
|
||||
await RemoteImages.withDb(async db => {
|
||||
Assert.deepEqual(
|
||||
db.data.images,
|
||||
[],
|
||||
"RemoteImages should have no images"
|
||||
);
|
||||
Assert.ok(
|
||||
!(await IOUtils.exists(
|
||||
PathUtils.join(REMOTE_IMAGES_PATH, IMAGE_INFO.recordId)
|
||||
)),
|
||||
"Image should have been deleted during cleanup"
|
||||
);
|
||||
});
|
||||
} finally {
|
||||
await RemoteImagesTestUtils.wipeCache();
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function test_remoteImages_migrate() {
|
||||
registerCleanupFunction(RemoteImagesTestUtils.wipeCache);
|
||||
|
||||
await RemoteImages.reset();
|
||||
await IOUtils.remove(REMOTE_IMAGES_DB_PATH);
|
||||
await RemoteImagesTestUtils.writeImage(
|
||||
RemoteImagesTestUtils.images.AboutRobots,
|
||||
RemoteImagesTestUtils.images.AboutRobots.filename
|
||||
);
|
||||
|
||||
await RemoteImages.withDb(async db => {
|
||||
const children = await IOUtils.getChildren(REMOTE_IMAGES_PATH);
|
||||
Assert.deepEqual(
|
||||
children,
|
||||
[],
|
||||
"RemoteImages migration should delete all images."
|
||||
try {
|
||||
await IOUtils.remove(REMOTE_IMAGES_DB_PATH);
|
||||
await RemoteImagesTestUtils.writeImage(
|
||||
RemoteImagesTestUtils.images.AboutRobots,
|
||||
RemoteImagesTestUtils.images.AboutRobots.filename
|
||||
);
|
||||
|
||||
await dbWriteFinished(db);
|
||||
const fromDisk = await IOUtils.readJSON(REMOTE_IMAGES_DB_PATH);
|
||||
await RemoteImages.withDb(async db => {
|
||||
const children = await IOUtils.getChildren(REMOTE_IMAGES_PATH);
|
||||
Assert.deepEqual(
|
||||
children,
|
||||
[],
|
||||
"RemoteImages migration should delete all images."
|
||||
);
|
||||
|
||||
Assert.deepEqual(
|
||||
fromDisk,
|
||||
db.data,
|
||||
"RemoteImages DB data should match on-disk contents"
|
||||
);
|
||||
await dbWriteFinished(db);
|
||||
const fromDisk = await IOUtils.readJSON(REMOTE_IMAGES_DB_PATH);
|
||||
|
||||
Assert.equal(db.data.version, 1, "RemoteImages DB version should be 1");
|
||||
Assert.deepEqual(
|
||||
db.data.images,
|
||||
{},
|
||||
"RemoteImages DB should have no entries"
|
||||
);
|
||||
});
|
||||
Assert.deepEqual(
|
||||
fromDisk,
|
||||
db.data,
|
||||
"RemoteImages DB data should match on-disk contents"
|
||||
);
|
||||
|
||||
Assert.equal(db.data.version, 1, "RemoteImages DB version should be 1");
|
||||
Assert.deepEqual(
|
||||
db.data.images,
|
||||
{},
|
||||
"RemoteImages DB should have no entries"
|
||||
);
|
||||
});
|
||||
} finally {
|
||||
await RemoteImagesTestUtils.wipeCache();
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function test_remoteImages_load_dedup() {
|
||||
const imageInfo = RemoteImagesTestUtils.images.AboutRobots;
|
||||
const sandbox = sinon.createSandbox();
|
||||
|
||||
const downloadSpy = sandbox.spy(Downloader.prototype, "downloadAsBytes");
|
||||
|
||||
const images = ["about-robots", "about-robots", "about-robots"];
|
||||
|
||||
const stop = await RemoteImagesTestUtils.serveRemoteImages(imageInfo);
|
||||
|
||||
try {
|
||||
const results = await RemoteImages.load(...images);
|
||||
RemoteImages.unload(results);
|
||||
|
||||
Assert.equal(
|
||||
results.size,
|
||||
1,
|
||||
"RemoteImages.load doesn't return duplicates"
|
||||
);
|
||||
|
||||
Assert.ok(
|
||||
downloadSpy.calledOnce,
|
||||
"RemoteImages.load doesn't download duplicates"
|
||||
);
|
||||
} finally {
|
||||
await stop();
|
||||
await RemoteImagesTestUtils.triggerCleanup();
|
||||
sandbox.restore();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -214,56 +214,71 @@ add_task(async function test_remoteL10n_content() {
|
|||
|
||||
add_task(async function test_remote_images_logo() {
|
||||
const imageInfo = RemoteImagesTestUtils.images.AboutRobots;
|
||||
const cleanup = await RemoteImagesTestUtils.serveRemoteImages(imageInfo);
|
||||
const stop = await RemoteImagesTestUtils.serveRemoteImages(imageInfo);
|
||||
|
||||
registerCleanupFunction(cleanup);
|
||||
try {
|
||||
const message = await getMessage("SPOTLIGHT_MESSAGE_93");
|
||||
message.content.logo = { imageId: imageInfo.recordId };
|
||||
|
||||
const message = await getMessage("SPOTLIGHT_MESSAGE_93");
|
||||
message.content.logo = { imageId: imageInfo.recordId };
|
||||
const dispatchStub = sinon.stub();
|
||||
const browser = BrowserWindowTracker.getTopWindow().gBrowser
|
||||
.selectedBrowser;
|
||||
|
||||
const dispatchStub = sinon.stub();
|
||||
const browser = BrowserWindowTracker.getTopWindow().gBrowser.selectedBrowser;
|
||||
await showAndWaitForDialog(
|
||||
{ message, browser, dispatchStub },
|
||||
async win => {
|
||||
await win.document.mozSubdialogReady;
|
||||
|
||||
await showAndWaitForDialog({ message, browser, dispatchStub }, async win => {
|
||||
await win.document.mozSubdialogReady;
|
||||
const logo = win.document.querySelector(".logo");
|
||||
|
||||
const logo = win.document.querySelector(".logo");
|
||||
ok(
|
||||
logo.src.startsWith("blob:"),
|
||||
"RemoteImages loaded a blob: URL in Spotlight"
|
||||
);
|
||||
|
||||
ok(
|
||||
logo.src.startsWith("blob:"),
|
||||
"RemoteImages loaded a blob: URL in Spotlight"
|
||||
win.document.getElementById("secondary").click();
|
||||
}
|
||||
);
|
||||
|
||||
win.document.getElementById("secondary").click();
|
||||
});
|
||||
} finally {
|
||||
await stop();
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function test_remoteImages_fail() {
|
||||
const imageInfo = RemoteImagesTestUtils.images.AboutRobots;
|
||||
registerCleanupFunction(
|
||||
await RemoteImagesTestUtils.serveRemoteImages(imageInfo)
|
||||
);
|
||||
const stop = await RemoteImagesTestUtils.serveRemoteImages(imageInfo);
|
||||
|
||||
const message = await getMessage("SPOTLIGHT_MESSAGE_93");
|
||||
message.content.logo = { imageId: "bogus" };
|
||||
try {
|
||||
const message = await getMessage("SPOTLIGHT_MESSAGE_93");
|
||||
message.content.logo = { imageId: "bogus" };
|
||||
|
||||
const dispatchStub = sinon.stub();
|
||||
const browser = BrowserWindowTracker.getTopWindow().gBrowser.selectedBrowser;
|
||||
const dispatchStub = sinon.stub();
|
||||
const browser = BrowserWindowTracker.getTopWindow().gBrowser
|
||||
.selectedBrowser;
|
||||
|
||||
await showAndWaitForDialog({ message, browser, dispatchStub }, async win => {
|
||||
await win.document.mozSubdialogReady;
|
||||
await showAndWaitForDialog(
|
||||
{ message, browser, dispatchStub },
|
||||
async win => {
|
||||
await win.document.mozSubdialogReady;
|
||||
|
||||
const logo = win.document.querySelector(".logo");
|
||||
const logo = win.document.querySelector(".logo");
|
||||
|
||||
Assert.ok(!logo.src.startsWith("blob:"), "RemoteImages did not patch URL");
|
||||
Assert.equal(
|
||||
logo.style.visibility,
|
||||
"hidden",
|
||||
"Spotlight hid image with missing URL"
|
||||
Assert.ok(
|
||||
!logo.src.startsWith("blob:"),
|
||||
"RemoteImages did not patch URL"
|
||||
);
|
||||
Assert.equal(
|
||||
logo.style.visibility,
|
||||
"hidden",
|
||||
"Spotlight hid image with missing URL"
|
||||
);
|
||||
|
||||
win.document.getElementById("secondary").click();
|
||||
}
|
||||
);
|
||||
|
||||
win.document.getElementById("secondary").click();
|
||||
});
|
||||
} finally {
|
||||
await stop();
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function test_contentExpanded() {
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
|
||||
var EXPORTED_SYMBOLS = ["PageDataSchema"];
|
||||
|
||||
Cu.importGlobalProperties(["fetch"]);
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
|
|
|
@ -10,13 +10,15 @@ const { XPCOMUtils } = ChromeUtils.import(
|
|||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
const { EventEmitter } = ChromeUtils.import(
|
||||
"resource://gre/modules/EventEmitter.jsm"
|
||||
);
|
||||
|
||||
const lazy = {};
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(lazy, {
|
||||
BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.jsm",
|
||||
E10SUtils: "resource://gre/modules/E10SUtils.jsm",
|
||||
EventEmitter: "resource://gre/modules/EventEmitter.jsm",
|
||||
HiddenFrame: "resource://gre/modules/HiddenFrame.jsm",
|
||||
PromiseUtils: "resource://gre/modules/PromiseUtils.jsm",
|
||||
});
|
||||
|
@ -270,7 +272,7 @@ class PageDataCache {
|
|||
* the format defined by the schemas at `browser/components/pagedata/schemas`.
|
||||
*/
|
||||
|
||||
const PageDataService = new (class PageDataService extends lazy.EventEmitter {
|
||||
const PageDataService = new (class PageDataService extends EventEmitter {
|
||||
/**
|
||||
* Caches page data discovered from browsers.
|
||||
*
|
||||
|
|
|
@ -7,11 +7,13 @@ const { XPCOMUtils } = ChromeUtils.import(
|
|||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
const { EventEmitter } = ChromeUtils.import(
|
||||
"resource://gre/modules/EventEmitter.jsm"
|
||||
);
|
||||
|
||||
const lazy = {};
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(lazy, {
|
||||
EventEmitter: "resource://gre/modules/EventEmitter.jsm",
|
||||
DeferredTask: "resource://gre/modules/DeferredTask.jsm",
|
||||
FilterAdult: "resource://activity-stream/lib/FilterAdult.jsm",
|
||||
PlacesUIUtils: "resource:///modules/PlacesUIUtils.jsm",
|
||||
|
@ -75,7 +77,7 @@ XPCOMUtils.defineLazyGetter(lazy, "logConsole", function() {
|
|||
* This component is intentionally decoupled from where the context comes from
|
||||
* so it can be unit tested.
|
||||
*/
|
||||
class SnapshotSelector extends lazy.EventEmitter {
|
||||
class SnapshotSelector extends EventEmitter {
|
||||
/**
|
||||
* All of the active selectors.
|
||||
*/
|
||||
|
@ -274,7 +276,12 @@ class SnapshotSelector extends lazy.EventEmitter {
|
|||
|
||||
lazy.logConsole.debug(
|
||||
`Found ${key} recommendations:`,
|
||||
recommendations.map(r => r.snapshot.url)
|
||||
recommendations.map(
|
||||
r =>
|
||||
`${r.snapshot.url} (score: ${r.score}${
|
||||
r.data ? ", data: " + JSON.stringify(r.data) : ""
|
||||
})`
|
||||
)
|
||||
);
|
||||
|
||||
return { recommendations, weight };
|
||||
|
|
|
@ -32,6 +32,9 @@ XPCOMUtils.defineLazyModuleGetters(lazy, {
|
|||
* The recommended snapshot.
|
||||
* @property {number} score
|
||||
* The score for this snapshot.
|
||||
* @property {object} [data]
|
||||
* An optional object containing data used to calculate the score, printed
|
||||
* as part of logs for debugging purposes.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -885,7 +888,7 @@ const Snapshots = new (class Snapshots {
|
|||
interactionCounts.min = Math.min(interactionCounts.min, interactions);
|
||||
return {
|
||||
snapshot: this.#translateRow(row),
|
||||
interactions,
|
||||
data: { interactions },
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -896,7 +899,7 @@ const Snapshots = new (class Snapshots {
|
|||
// For now instead we assign a score based on the number of interactions
|
||||
// with the page during `snapshot_timeofday_limit_days`.
|
||||
entries.forEach(e => {
|
||||
e.score = this.timeOfDayScore(e.interactions, interactionCounts);
|
||||
e.score = this.timeOfDayScore(e.data.interactions, interactionCounts);
|
||||
});
|
||||
return entries;
|
||||
}
|
||||
|
|
|
@ -245,27 +245,21 @@ async function handlePromoOnPreload(message) {
|
|||
}
|
||||
}
|
||||
|
||||
async function setupFeatureConfig() {
|
||||
async function setupMessageConfig() {
|
||||
let config = null;
|
||||
let message = null;
|
||||
|
||||
let hideDefault = window.PrivateBrowsingShouldHideDefault();
|
||||
try {
|
||||
config = window.PrivateBrowsingFeatureConfig();
|
||||
let response = await window.ASRouterMessage({
|
||||
type: "PBNEWTAB_MESSAGE_REQUEST",
|
||||
data: { hideDefault: !!hideDefault },
|
||||
});
|
||||
message = response?.message;
|
||||
config = message?.content;
|
||||
config.messageId = message?.id;
|
||||
} catch (e) {}
|
||||
|
||||
if (!Object.keys(config).length) {
|
||||
let hideDefault = window.PrivateBrowsingShouldHideDefault();
|
||||
try {
|
||||
let response = await window.ASRouterMessage({
|
||||
type: "PBNEWTAB_MESSAGE_REQUEST",
|
||||
data: { hideDefault: !!hideDefault },
|
||||
});
|
||||
message = response?.message;
|
||||
config = message?.content;
|
||||
config.messageId = message?.id;
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
await renderInfo(config);
|
||||
let hasRendered = await renderPromo(config);
|
||||
if (hasRendered && message) {
|
||||
|
@ -290,7 +284,7 @@ document.addEventListener("DOMContentLoaded", function() {
|
|||
|
||||
// We don't do this setup until now, because we don't want to record any impressions until we're
|
||||
// sure we're actually running a private window, not just about:privatebrowsing in a normal window.
|
||||
setupFeatureConfig();
|
||||
setupMessageConfig();
|
||||
|
||||
// Set up the private search banner.
|
||||
const privateSearchBanner = document.getElementById("search-banner");
|
||||
|
|
|
@ -8,10 +8,10 @@ add_task(async function test_experiment_plain_text() {
|
|||
const defaultMessageContent = (await PanelTestProvider.getMessages()).find(
|
||||
m => m.template === "pb_newtab"
|
||||
).content;
|
||||
let doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({
|
||||
featureId: "privatebrowsing",
|
||||
enabled: true,
|
||||
value: {
|
||||
let doExperimentCleanup = await setupMSExperimentWithMessage({
|
||||
id: "PB_NEWTAB_MESSAGING_SYSTEM",
|
||||
template: "pb_newtab",
|
||||
content: {
|
||||
...defaultMessageContent,
|
||||
infoTitle: "Hello world",
|
||||
infoTitleEnabled: true,
|
||||
|
@ -22,6 +22,10 @@ add_task(async function test_experiment_plain_text() {
|
|||
promoLinkText: "Promo link",
|
||||
promoLinkUrl: "https://test.com",
|
||||
},
|
||||
// Priority ensures this message is picked over the one in
|
||||
// OnboardingMessageProvider
|
||||
priority: 5,
|
||||
targeting: "true",
|
||||
});
|
||||
|
||||
let { win, tab } = await openTabAndWaitForRender();
|
||||
|
@ -57,53 +61,17 @@ add_task(async function test_experiment_plain_text() {
|
|||
await doExperimentCleanup();
|
||||
});
|
||||
|
||||
add_task(async function test_experiment_fluent() {
|
||||
const defaultMessageContent = (await PanelTestProvider.getMessages()).find(
|
||||
m => m.template === "pb_newtab"
|
||||
).content;
|
||||
let doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({
|
||||
featureId: "privatebrowsing",
|
||||
enabled: true,
|
||||
value: {
|
||||
...defaultMessageContent,
|
||||
infoBody: "fluent:about-private-browsing-info-title",
|
||||
promoLinkText: "fluent:about-private-browsing-prominent-cta",
|
||||
promoLinkUrl: "https://test.com",
|
||||
},
|
||||
});
|
||||
|
||||
let { win, tab } = await openTabAndWaitForRender();
|
||||
|
||||
await SpecialPowers.spawn(tab, [], async function() {
|
||||
const infoBody = content.document.getElementById("info-body");
|
||||
const promoLink = content.document.getElementById(
|
||||
"private-browsing-vpn-link"
|
||||
);
|
||||
|
||||
// Check experiment values are rendered
|
||||
is(
|
||||
infoBody.textContent,
|
||||
"You’re in a Private Window",
|
||||
"should render infoBody with fluent"
|
||||
);
|
||||
is(
|
||||
promoLink.textContent,
|
||||
"Stay private with Mozilla VPN",
|
||||
"should render promoLinkText with fluent"
|
||||
);
|
||||
});
|
||||
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
await doExperimentCleanup();
|
||||
});
|
||||
|
||||
add_task(async function test_experiment_info_disabled() {
|
||||
let doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({
|
||||
featureId: "privatebrowsing",
|
||||
enabled: true,
|
||||
value: {
|
||||
let doExperimentCleanup = await setupMSExperimentWithMessage({
|
||||
id: "PB_NEWTAB_MESSAGING_SYSTEM",
|
||||
template: "pb_newtab",
|
||||
content: {
|
||||
infoEnabled: false,
|
||||
},
|
||||
// Priority ensures this message is picked over the one in
|
||||
// OnboardingMessageProvider
|
||||
priority: 5,
|
||||
targeting: "true",
|
||||
});
|
||||
|
||||
let { win, tab } = await openTabAndWaitForRender();
|
||||
|
@ -121,12 +89,16 @@ add_task(async function test_experiment_info_disabled() {
|
|||
});
|
||||
|
||||
add_task(async function test_experiment_promo_disabled() {
|
||||
let doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({
|
||||
featureId: "privatebrowsing",
|
||||
enabled: true,
|
||||
value: {
|
||||
let doExperimentCleanup = await setupMSExperimentWithMessage({
|
||||
id: "PB_NEWTAB_MESSAGING_SYSTEM",
|
||||
template: "pb_newtab",
|
||||
content: {
|
||||
promoEnabled: false,
|
||||
},
|
||||
// Priority ensures this message is picked over the one in
|
||||
// OnboardingMessageProvider
|
||||
priority: 5,
|
||||
targeting: "true",
|
||||
});
|
||||
|
||||
let { win, tab } = await openTabAndWaitForRender();
|
||||
|
@ -145,15 +117,19 @@ add_task(async function test_experiment_promo_disabled() {
|
|||
|
||||
add_task(async function test_experiment_format_urls() {
|
||||
const LOCALE = Services.locale.appLocaleAsBCP47;
|
||||
let doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({
|
||||
featureId: "privatebrowsing",
|
||||
enabled: true,
|
||||
value: {
|
||||
let doExperimentCleanup = await setupMSExperimentWithMessage({
|
||||
id: "PB_NEWTAB_MESSAGING_SYSTEM",
|
||||
template: "pb_newtab",
|
||||
content: {
|
||||
infoEnabled: true,
|
||||
promoEnabled: true,
|
||||
infoLinkUrl: "http://foo.mozilla.com/%LOCALE%",
|
||||
promoLinkUrl: "http://bar.mozilla.com/%LOCALE%",
|
||||
},
|
||||
// Priority ensures this message is picked over the one in
|
||||
// OnboardingMessageProvider
|
||||
priority: 5,
|
||||
targeting: "true",
|
||||
});
|
||||
|
||||
let { win, tab } = await openTabAndWaitForRender();
|
||||
|
@ -176,13 +152,17 @@ add_task(async function test_experiment_format_urls() {
|
|||
});
|
||||
|
||||
add_task(async function test_experiment_click_info_telemetry() {
|
||||
let doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({
|
||||
featureId: "privatebrowsing",
|
||||
enabled: true,
|
||||
value: {
|
||||
let doExperimentCleanup = await setupMSExperimentWithMessage({
|
||||
id: "PB_NEWTAB_MESSAGING_SYSTEM_CLICK_INFO_TELEM",
|
||||
template: "pb_newtab",
|
||||
content: {
|
||||
infoEnabled: true,
|
||||
infoLinkUrl: "http://example.com",
|
||||
},
|
||||
// Priority ensures this message is picked over the one in
|
||||
// OnboardingMessageProvider
|
||||
priority: 5,
|
||||
targeting: "true",
|
||||
});
|
||||
|
||||
// Required for `mach test --verify`
|
||||
|
@ -207,13 +187,17 @@ add_task(async function test_experiment_click_info_telemetry() {
|
|||
});
|
||||
|
||||
add_task(async function test_experiment_click_promo_telemetry() {
|
||||
let doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({
|
||||
featureId: "privatebrowsing",
|
||||
enabled: true,
|
||||
value: {
|
||||
let doExperimentCleanup = await setupMSExperimentWithMessage({
|
||||
id: `PB_NEWTAB_MESSAGING_SYSTEM_PROMO_TELEM_${Math.random()}`,
|
||||
template: "pb_newtab",
|
||||
content: {
|
||||
promoEnabled: true,
|
||||
promoLinkUrl: "http://example.com",
|
||||
},
|
||||
// Priority ensures this message is picked over the one in
|
||||
// OnboardingMessageProvider
|
||||
priority: 5,
|
||||
targeting: "true",
|
||||
});
|
||||
|
||||
let { win, tab } = await openTabAndWaitForRender();
|
||||
|
@ -240,13 +224,15 @@ add_task(async function test_experiment_bottom_promo() {
|
|||
const defaultMessageContent = (await PanelTestProvider.getMessages()).find(
|
||||
m => m.template === "pb_newtab"
|
||||
).content;
|
||||
let doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({
|
||||
featureId: "privatebrowsing",
|
||||
value: {
|
||||
|
||||
let doExperimentCleanup = await setupMSExperimentWithMessage({
|
||||
id: "PB_NEWTAB_MESSAGING_SYSTEM",
|
||||
template: "pb_newtab",
|
||||
content: {
|
||||
...defaultMessageContent,
|
||||
enabled: true,
|
||||
promoEnabled: true,
|
||||
promoLinkType: "button",
|
||||
promoLinkUrl: "http://example.com",
|
||||
promoLinkUrl: "http://bar.example.com/%LOCALE%",
|
||||
promoSectionStyle: "bottom",
|
||||
promoHeader: "Need more privacy?",
|
||||
infoTitleEnabled: true,
|
||||
|
@ -254,6 +240,10 @@ add_task(async function test_experiment_bottom_promo() {
|
|||
promoImageLarge: "",
|
||||
promoImageSmall: "chrome://browser/content/assets/vpn-logo.svg",
|
||||
},
|
||||
// Priority ensures this message is picked over the one in
|
||||
// OnboardingMessageProvider
|
||||
priority: 5,
|
||||
targeting: "true",
|
||||
});
|
||||
|
||||
let { win, tab } = await openTabAndWaitForRender();
|
||||
|
@ -277,7 +267,7 @@ add_task(async function test_experiment_bottom_promo() {
|
|||
);
|
||||
ok(
|
||||
!content.document.querySelector("#private-browsing-vpn-text"),
|
||||
"Should not render promo title if promoTitleEnabled is true"
|
||||
"Should not render promo title if promoTitleEnabled is false"
|
||||
);
|
||||
ok(
|
||||
content.document.querySelector("#info-title"),
|
||||
|
@ -297,11 +287,12 @@ add_task(async function test_experiment_below_search_promo() {
|
|||
const defaultMessageContent = (await PanelTestProvider.getMessages()).find(
|
||||
m => m.template === "pb_newtab"
|
||||
).content;
|
||||
let doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({
|
||||
featureId: "privatebrowsing",
|
||||
value: {
|
||||
let doExperimentCleanup = await setupMSExperimentWithMessage({
|
||||
id: "PB_NEWTAB_MESSAGING_SYSTEM",
|
||||
template: "pb_newtab",
|
||||
content: {
|
||||
...defaultMessageContent,
|
||||
enabled: true,
|
||||
promoEnabled: true,
|
||||
promoLinkType: "button",
|
||||
promoLinkUrl: "http://example.com",
|
||||
promoSectionStyle: "below-search",
|
||||
|
@ -312,6 +303,10 @@ add_task(async function test_experiment_below_search_promo() {
|
|||
promoImageSmall: "chrome://browser/content/assets/vpn-logo.svg",
|
||||
infoTitleEnabled: false,
|
||||
},
|
||||
// Priority ensures this message is picked over the one in
|
||||
// OnboardingMessageProvider
|
||||
priority: 5,
|
||||
targeting: "true",
|
||||
});
|
||||
|
||||
let { win, tab } = await openTabAndWaitForRender();
|
||||
|
@ -356,11 +351,12 @@ add_task(async function test_experiment_top_promo() {
|
|||
const defaultMessageContent = (await PanelTestProvider.getMessages()).find(
|
||||
m => m.template === "pb_newtab"
|
||||
).content;
|
||||
let doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({
|
||||
featureId: "privatebrowsing",
|
||||
value: {
|
||||
let doExperimentCleanup = await setupMSExperimentWithMessage({
|
||||
id: `PB_NEWTAB_MESSAGING_SYSTEM_DISMISS_${Math.random()}`,
|
||||
template: "pb_newtab",
|
||||
content: {
|
||||
...defaultMessageContent,
|
||||
enabled: true,
|
||||
promoEnabled: true,
|
||||
promoLinkType: "button",
|
||||
promoLinkUrl: "http://example.com",
|
||||
promoSectionStyle: "top",
|
||||
|
@ -371,6 +367,10 @@ add_task(async function test_experiment_top_promo() {
|
|||
promoImageSmall: "chrome://browser/content/assets/vpn-logo.svg",
|
||||
infoTitleEnabled: false,
|
||||
},
|
||||
// Priority ensures this message is picked over the one in
|
||||
// OnboardingMessageProvider
|
||||
priority: 5,
|
||||
targeting: "true",
|
||||
});
|
||||
|
||||
let { win, tab } = await openTabAndWaitForRender();
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
function handleRequest(req, resp) {
|
||||
resp.setHeader("Content-Type", "text/html", false);
|
||||
if (req.hasHeader("Origin")) {
|
||||
if (req.hasHeader("Origin") && req.getHeader("Origin") != "null") {
|
||||
resp.write("error");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -230,6 +230,9 @@ const { XPCOMUtils } = ChromeUtils.import(
|
|||
const { AppConstants } = ChromeUtils.import(
|
||||
"resource://gre/modules/AppConstants.jsm"
|
||||
);
|
||||
const { GlobalState } = ChromeUtils.import(
|
||||
"resource:///modules/sessionstore/GlobalState.jsm"
|
||||
);
|
||||
|
||||
const lazy = {};
|
||||
|
||||
|
@ -248,7 +251,6 @@ XPCOMUtils.defineLazyModuleGetters(lazy, {
|
|||
BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.jsm",
|
||||
DevToolsShim: "chrome://devtools-startup/content/DevToolsShim.jsm",
|
||||
E10SUtils: "resource://gre/modules/E10SUtils.jsm",
|
||||
GlobalState: "resource:///modules/sessionstore/GlobalState.jsm",
|
||||
HomePage: "resource:///modules/HomePage.jsm",
|
||||
PrivacyFilter: "resource://gre/modules/sessionstore/PrivacyFilter.jsm",
|
||||
PromiseUtils: "resource://gre/modules/PromiseUtils.jsm",
|
||||
|
@ -606,7 +608,7 @@ var SessionStoreInternal = {
|
|||
"nsISupportsWeakReference",
|
||||
]),
|
||||
|
||||
_globalState: new lazy.GlobalState(),
|
||||
_globalState: new GlobalState(),
|
||||
|
||||
// A counter to be used to generate a unique ID for each closed tab or window.
|
||||
_nextClosedId: 0,
|
||||
|
|
|
@ -33,66 +33,62 @@ addNonCoopTask(
|
|||
|
||||
async function test_restore_text_data_subframes(aURL) {
|
||||
// Add a new tab.
|
||||
let tab = BrowserTestUtils.addTab(gBrowser, aURL);
|
||||
await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, aURL);
|
||||
|
||||
// "Type in" some random values.
|
||||
await SpecialPowers.spawn(tab.linkedBrowser, [], async function() {
|
||||
function typeText(aTextField, aValue) {
|
||||
aTextField.value = aValue;
|
||||
await setPropertyOfFormField(
|
||||
tab.linkedBrowser,
|
||||
"#out1",
|
||||
"value",
|
||||
Date.now().toString(16)
|
||||
);
|
||||
|
||||
let event = aTextField.ownerDocument.createEvent("UIEvents");
|
||||
event.initUIEvent("input", true, true, aTextField.ownerGlobal, 0);
|
||||
aTextField.dispatchEvent(event);
|
||||
}
|
||||
typeText(content.document.getElementById("out1"), Date.now().toString(16));
|
||||
typeText(content.document.getElementsByName("1|#out2")[0], Math.random());
|
||||
await SpecialPowers.spawn(content.frames[0], [], async function() {
|
||||
await SpecialPowers.spawn(content.frames[1], [], async function() {
|
||||
function typeText2(aTextField, aValue) {
|
||||
aTextField.value = aValue;
|
||||
await setPropertyOfFormField(
|
||||
tab.linkedBrowser,
|
||||
"input[name='1|#out2']",
|
||||
"value",
|
||||
Math.random()
|
||||
);
|
||||
|
||||
let event = aTextField.ownerDocument.createEvent("UIEvents");
|
||||
event.initUIEvent("input", true, true, aTextField.ownerGlobal, 0);
|
||||
aTextField.dispatchEvent(event);
|
||||
}
|
||||
typeText2(content.document.getElementById("in1"), new Date());
|
||||
});
|
||||
});
|
||||
});
|
||||
await setPropertyOfFormField(
|
||||
tab.linkedBrowser.browsingContext.children[0].children[1],
|
||||
"#in1",
|
||||
"value",
|
||||
new Date()
|
||||
);
|
||||
|
||||
// Duplicate the tab.
|
||||
let tab2 = gBrowser.duplicateTab(tab);
|
||||
let browser2 = tab2.linkedBrowser;
|
||||
await promiseTabRestored(tab2);
|
||||
|
||||
isnot(
|
||||
await getPropertyOfFormField(browser2, "#out1", "value"),
|
||||
await getPropertyOfFormField(
|
||||
browser2.browsingContext.children[1],
|
||||
"#out1",
|
||||
"value"
|
||||
),
|
||||
"text isn't reused for frames"
|
||||
);
|
||||
|
||||
isnot(
|
||||
await getPropertyOfFormField(browser2, "input[name='1|#out2']", "value"),
|
||||
"",
|
||||
"text containing | and # is correctly restored"
|
||||
);
|
||||
|
||||
is(
|
||||
await getPropertyOfFormField(
|
||||
browser2.browsingContext.children[1],
|
||||
"#out2",
|
||||
"value"
|
||||
),
|
||||
"",
|
||||
"id prefixes can't be faked"
|
||||
);
|
||||
|
||||
// Query a few values from the top and its child frames.
|
||||
await SpecialPowers.spawn(tab2.linkedBrowser, [], async function() {
|
||||
let out1Val = await SpecialPowers.spawn(
|
||||
content.frames[1],
|
||||
[],
|
||||
async function() {
|
||||
return content.document.getElementById("out1").value;
|
||||
}
|
||||
);
|
||||
Assert.notEqual(
|
||||
content.document.getElementById("out1").value,
|
||||
out1Val,
|
||||
"text isn't reused for frames"
|
||||
);
|
||||
Assert.notEqual(
|
||||
content.document.getElementsByName("1|#out2")[0].value,
|
||||
"",
|
||||
"text containing | and # is correctly restored"
|
||||
);
|
||||
let out2Val = await SpecialPowers.spawn(
|
||||
content.frames[1],
|
||||
[],
|
||||
async function() {
|
||||
return content.document.getElementById("out2").value;
|
||||
}
|
||||
);
|
||||
Assert.equal(out2Val, "", "id prefixes can't be faked");
|
||||
|
||||
// Bug 588077
|
||||
// XXX(farre): disabling this, because it started passing more heavily on Windows.
|
||||
/*
|
||||
|
@ -107,19 +103,17 @@ async function test_restore_text_data_subframes(aURL) {
|
|||
);
|
||||
todo_is(in1ValFrame0_1, "", "id prefixes aren't mixed up");
|
||||
*/
|
||||
|
||||
let in1ValFrame1_0 = await SpecialPowers.spawn(
|
||||
content.frames[1],
|
||||
[],
|
||||
async function() {
|
||||
return SpecialPowers.spawn(content.frames[0], [], async function() {
|
||||
return content.document.getElementById("in1").value;
|
||||
});
|
||||
}
|
||||
);
|
||||
Assert.equal(in1ValFrame1_0, "", "id prefixes aren't mixed up");
|
||||
});
|
||||
|
||||
is(
|
||||
await getPropertyOfFormField(
|
||||
browser2.browsingContext.children[1].children[0],
|
||||
"#in1",
|
||||
"value"
|
||||
),
|
||||
"",
|
||||
"id prefixes aren't mixed up"
|
||||
);
|
||||
// Cleanup.
|
||||
gBrowser.removeTab(tab2);
|
||||
gBrowser.removeTab(tab);
|
||||
|
|
|
@ -17,8 +17,6 @@ const { XPCOMUtils } = ChromeUtils.import(
|
|||
);
|
||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGlobalGetters(this, ["fetch"]);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
ProfileAge: "resource://gre/modules/ProfileAge.jsm",
|
||||
UrlbarPrefs: "resource:///modules/UrlbarPrefs.jsm",
|
||||
|
|
|
@ -28,8 +28,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
|||
UrlbarUtils: "resource:///modules/UrlbarUtils.jsm",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGlobalGetters(this, ["crypto", "fetch"]);
|
||||
|
||||
const TIMESTAMP_TEMPLATE = "%YYYYMMDDHH%";
|
||||
const TIMESTAMP_LENGTH = 10;
|
||||
const TIMESTAMP_REGEXP = /^\d{10}$/;
|
||||
|
|
|
@ -8,7 +8,6 @@ This is the nascent documentation of the Firefox front-end code.
|
|||
:maxdepth: 2
|
||||
|
||||
urlbar/index
|
||||
/toolkit/mozapps/update/docs/BackgroundUpdates
|
||||
BrowserUsageTelemetry
|
||||
CommandLineParameters
|
||||
components/enterprisepolicies/docs/index
|
||||
|
|
|
@ -165,7 +165,7 @@ const AVAILABLE_SHIMS = [
|
|||
types: ["image", "imageset", "xmlhttprequest"],
|
||||
},
|
||||
],
|
||||
onlyIfDFPIActive: true,
|
||||
onlyIfBlockedByETP: true,
|
||||
},
|
||||
{
|
||||
id: "AdSafeProtectedGoogleIMAAdapter",
|
||||
|
@ -545,7 +545,7 @@ const AVAILABLE_SHIMS = [
|
|||
types: ["image", "imageset", "xmlhttprequest"],
|
||||
},
|
||||
],
|
||||
onlyIfDFPIActive: true,
|
||||
onlyIfBlockedByETP: true,
|
||||
},
|
||||
{
|
||||
id: "Vidible",
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"manifest_version": 2,
|
||||
"name": "Web Compatibility Interventions",
|
||||
"description": "Urgent post-release fixes for web compatibility.",
|
||||
"version": "102.11.0",
|
||||
"version": "102.13.0",
|
||||
"applications": {
|
||||
"gecko": {
|
||||
"id": "webcompat@mozilla.org",
|
||||
|
|
|
@ -174,3 +174,14 @@ if (window[window.GoogleAnalyticsObject || "ga"]?.loaded === undefined) {
|
|||
// Run dataLayer.hide.end to handle asynchide (bug 1628151)
|
||||
run(window.dataLayer?.hide?.end);
|
||||
}
|
||||
|
||||
if (!window?.gaplugins?.Linker) {
|
||||
window.gaplugins = window.gaplugins || {};
|
||||
window.gaplugins.Linker = class {
|
||||
autoLink() {}
|
||||
decorate(url) {
|
||||
return url;
|
||||
}
|
||||
passthrough() {}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -123,7 +123,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "477713442405d727148d74b07fe5de3cac5ffbac"
|
||||
"revision": "ab457d20536cdad54f18c6f6e6cebfee7f5b4a6a"
|
||||
},
|
||||
"bg": {
|
||||
"pin": false,
|
||||
|
@ -159,7 +159,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "483ebc0eec582865c896a82ad12cfb0c0c3dba3b"
|
||||
"revision": "dbbc175612ace7929bb0cf161ce9d823eafb3004"
|
||||
},
|
||||
"bo": {
|
||||
"pin": false,
|
||||
|
@ -483,7 +483,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "f2fe1f5df117080bdcb664ad545c7619ddd2070a"
|
||||
"revision": "40b5590086e9b32742f2fa3db7c80437139e6eb0"
|
||||
},
|
||||
"es-CL": {
|
||||
"pin": false,
|
||||
|
@ -555,7 +555,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "d5ec66c46af2a98a4bd25df5c994c08291fac0de"
|
||||
"revision": "3b129b698a2f30a1c8dae7f8968786b0ee08135c"
|
||||
},
|
||||
"eu": {
|
||||
"pin": false,
|
||||
|
@ -627,7 +627,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "036521c5740106d4349400b81fe3fa1e2f7d0a43"
|
||||
"revision": "af0706d0cf385ac9436c67055804860f9e94001c"
|
||||
},
|
||||
"fr": {
|
||||
"pin": false,
|
||||
|
@ -663,7 +663,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "c00b44f074b8ad9b622f1daab871d54d2d1645ee"
|
||||
"revision": "e3b53c4c7a7d49418d6b12d40128aae0b513410a"
|
||||
},
|
||||
"ga-IE": {
|
||||
"pin": false,
|
||||
|
@ -951,7 +951,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "65370babd8731f8278b79ea0b74f465f4dc39887"
|
||||
"revision": "714abf1ab272afd53ab6bea729d1bda22f6441da"
|
||||
},
|
||||
"ja": {
|
||||
"pin": false,
|
||||
|
@ -1011,7 +1011,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "8e6fbf4edc5bd5f6daafbba7d4e3fe5558b79407"
|
||||
"revision": "9f1681ad30765dc1098e0668de59d953ab732a5a"
|
||||
},
|
||||
"kk": {
|
||||
"pin": false,
|
||||
|
@ -1317,7 +1317,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "c395fc5b6bb54bdb75275dcde13a2b9f8e0fc60f"
|
||||
"revision": "afef0210f7e634d6e548c8d022e5b2a53861cf0a"
|
||||
},
|
||||
"nn-NO": {
|
||||
"pin": false,
|
||||
|
@ -1335,7 +1335,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "4598fb2e432dd8a22069fd6c16a0119ffc86f33e"
|
||||
"revision": "28bdd662868540209fdad943df879806528b1693"
|
||||
},
|
||||
"oc": {
|
||||
"pin": false,
|
||||
|
@ -1353,7 +1353,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "a2795507470ca965d783a8fdf04522b79aca3170"
|
||||
"revision": "bb392bb97d78d2a5d680fb4c0529fa4eee6cc312"
|
||||
},
|
||||
"pa-IN": {
|
||||
"pin": false,
|
||||
|
@ -1371,7 +1371,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "613a0f7506b0bd3a289eb841ccad4b8b6d8a2c53"
|
||||
"revision": "d049479fe4de64b8e5af760f1dd9e0b985f04700"
|
||||
},
|
||||
"pl": {
|
||||
"pin": false,
|
||||
|
@ -1407,7 +1407,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "222b020e3b81acc865482d5431df6c7f42780d93"
|
||||
"revision": "3f34c89e3f254b86bee63146c79c6336c77a61e3"
|
||||
},
|
||||
"pt-PT": {
|
||||
"pin": false,
|
||||
|
@ -1425,7 +1425,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "198b02d912931955c81337a225cc8898cbb6e0d7"
|
||||
"revision": "012095d45e7dfedde3f2ae924005db743bec4926"
|
||||
},
|
||||
"rm": {
|
||||
"pin": false,
|
||||
|
@ -1605,7 +1605,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "28103aabc4f3ac18218cd3b446f5c4f014a06c4a"
|
||||
"revision": "f08c322f36f1ce75ed553fad2c6274d707635ef6"
|
||||
},
|
||||
"son": {
|
||||
"pin": false,
|
||||
|
@ -1767,7 +1767,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "7973fb73283f5649e7e3a573aa1114f46663e6e8"
|
||||
"revision": "1af51f1f890cd94aed334bd335f5dfac56076c56"
|
||||
},
|
||||
"tl": {
|
||||
"pin": false,
|
||||
|
@ -1803,7 +1803,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "fd0e0955e3f64b76f3989740f738ca61639f9938"
|
||||
"revision": "acfcc1ead9c1a6e216a7208fa6052c0573a1b334"
|
||||
},
|
||||
"trs": {
|
||||
"pin": false,
|
||||
|
@ -1893,7 +1893,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "acddeae5f5a6744f7b4bece74d8360d9d1aaa4fc"
|
||||
"revision": "c9537a6c9ddd734253e6ac6d64e2f9eb60d0648e"
|
||||
},
|
||||
"wo": {
|
||||
"pin": false,
|
||||
|
@ -1947,7 +1947,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "26c5b9170419a95f54cfa6a80fdb52d557a32256"
|
||||
"revision": "ccdf7081c85960340e57b23c5bf31bc057f64cf3"
|
||||
},
|
||||
"zh-TW": {
|
||||
"pin": false,
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
Cu.importGlobalProperties(["fetch"]);
|
||||
|
||||
var EXPORTED_SYMBOLS = [
|
||||
"PartnerLinkAttribution",
|
||||
"CONTEXTUAL_SERVICES_PING_TYPES",
|
||||
|
|
|
@ -683,7 +683,7 @@
|
|||
|
||||
/* Firefox View button */
|
||||
|
||||
:is(#firefox-view-button, #wrapper-firefox-view-button) + #tabbrowser-tabs {
|
||||
:root:not([privatebrowsingmode=temporary]) :is(#firefox-view-button, #wrapper-firefox-view-button) + #tabbrowser-tabs {
|
||||
border-inline-start: 1px solid color-mix(in srgb, currentColor 25%, transparent);
|
||||
padding-inline-start: calc(var(--tab-overflow-pinned-tabs-width) + 4px);
|
||||
margin-inline-start: 4px;
|
||||
|
|
|
@ -186,13 +186,13 @@ toolbar .toolbarbutton-1:not([disabled=true]):is([open],[checked],:hover:active)
|
|||
}
|
||||
|
||||
/* Keyboard focus styling */
|
||||
.titlebar-button:focus-visible,
|
||||
#PersonalToolbar .toolbarbutton-1:focus-visible,
|
||||
findbar toolbarbutton.tabbable:focus-visible,
|
||||
toolbarbutton.bookmark-item:not(.subviewbutton):focus-visible,
|
||||
toolbar:not(#PersonalToolbar) .toolbarbutton-1:focus-visible > .toolbarbutton-icon,
|
||||
toolbar:not(#PersonalToolbar) .toolbarbutton-1:focus-visible > .toolbarbutton-text,
|
||||
toolbar:not(#PersonalToolbar) .toolbarbutton-1:focus-visible > .toolbarbutton-badge-stack {
|
||||
color: inherit;
|
||||
outline: var(--focus-outline);
|
||||
outline-offset: var(--focus-outline-inset);
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ allprojects {
|
|||
topsrcdir = gradle.mozconfig.topsrcdir
|
||||
topobjdir = gradle.mozconfig.topobjdir
|
||||
|
||||
gleanVersion = "50.0.1"
|
||||
gleanVersion = "50.1.0"
|
||||
if (gleanVersion != getRustVersionFor("glean")) {
|
||||
throw new StopExecutionException("Mismatched Glean version, expected: ${gleanVersion}," +
|
||||
" found ${getRustVersionFor("glean")}")
|
||||
|
|
|
@ -20,16 +20,38 @@ option(
|
|||
set_config("MOZ_UPDATER", True, when="--enable-updater")
|
||||
set_define("MOZ_UPDATER", True, when="--enable-updater")
|
||||
|
||||
# Verify MAR signatures
|
||||
# Updates that do not verify signatures
|
||||
# ==============================================================
|
||||
|
||||
option("--disable-verify-mar", help="Disable verifying MAR signatures")
|
||||
option(
|
||||
"--enable-unverified-updates",
|
||||
default=False,
|
||||
help="Enable application update without verifying MAR or updater binary signatures",
|
||||
)
|
||||
|
||||
|
||||
@depends("--enable-unverified-updates", "--enable-compile-environment")
|
||||
def disable_unverified_updates(unverified_updates, compile_environment):
|
||||
if unverified_updates:
|
||||
if not compile_environment:
|
||||
die("--enable-unverified-updates requires --enable-compile-environment")
|
||||
return not unverified_updates
|
||||
|
||||
|
||||
set_define(
|
||||
"MOZ_VERIFY_MAR_SIGNATURE", depends_if("--enable-verify-mar")(lambda _: True)
|
||||
"MOZ_VERIFY_MAR_SIGNATURE",
|
||||
depends_if(disable_unverified_updates)(lambda _: True),
|
||||
)
|
||||
set_config(
|
||||
"MOZ_VERIFY_MAR_SIGNATURE", depends_if("--enable-verify-mar")(lambda _: True)
|
||||
"MOZ_VERIFY_MAR_SIGNATURE",
|
||||
True,
|
||||
depends_if(disable_unverified_updates)(lambda _: True),
|
||||
)
|
||||
|
||||
set_config(
|
||||
"DISABLE_UPDATER_AUTHENTICODE_CHECK",
|
||||
True,
|
||||
depends_if("--enable-unverified-updates")(lambda _: True),
|
||||
)
|
||||
|
||||
# Maintenance service (Windows only)
|
||||
|
|
17
build/rust/wasi/Cargo.toml
Normal file
17
build/rust/wasi/Cargo.toml
Normal file
|
@ -0,0 +1,17 @@
|
|||
[package]
|
||||
name = "wasi"
|
||||
version = "0.10.0+wasi-snapshot-preview999"
|
||||
edition = "2018"
|
||||
license = "MPL-2.0"
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies.wasi]
|
||||
version = "0.11"
|
||||
default-features = false
|
||||
|
||||
[features]
|
||||
default = ["wasi/default"]
|
||||
rustc-dep-of-std = ["wasi/rustc-dep-of-std"]
|
||||
std = ["wasi/std"]
|
5
build/rust/wasi/lib.rs
Normal file
5
build/rust/wasi/lib.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
/* 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/. */
|
||||
|
||||
pub use wasi::*;
|
|
@ -105,17 +105,6 @@ class SourcesTree extends Component {
|
|||
);
|
||||
}
|
||||
|
||||
if (
|
||||
nextProps.selectedSource &&
|
||||
nextProps.selectedSource != selectedSource
|
||||
) {
|
||||
const highlightItems = getDirectories(
|
||||
nextProps.selectedSource,
|
||||
sourceTree
|
||||
);
|
||||
this.setState({ highlightItems });
|
||||
}
|
||||
|
||||
// NOTE: do not run this every time a source is clicked,
|
||||
// only when a new source is added
|
||||
if (nextProps.sources != this.props.sources) {
|
||||
|
@ -128,9 +117,43 @@ class SourcesTree extends Component {
|
|||
sourceTree,
|
||||
});
|
||||
if (update) {
|
||||
this.setState(update);
|
||||
this.setState({
|
||||
uncollapsedTree: update.uncollapsedTree,
|
||||
sourceTree: update.sourceTree,
|
||||
getParent: update.getParent,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Execute this *after* the call to updateTree in case the selected source
|
||||
// just got added in the props.
|
||||
if (
|
||||
nextProps.selectedSource &&
|
||||
nextProps.selectedSource != selectedSource
|
||||
) {
|
||||
const highlightItems = getDirectories(
|
||||
nextProps.selectedSource,
|
||||
// Ensure querying latest state, in case updateTree updated the source tree
|
||||
this.state.sourceTree
|
||||
);
|
||||
this.setState({ highlightItems });
|
||||
|
||||
// Also, it can happen that the source is selected before it is registered in the tree,
|
||||
// In which case, this previous line would select the root item.
|
||||
// So check if we have a selectedSource and we are on root and we got new sources,
|
||||
// to try to update the selected item in the ManagedTree
|
||||
} else if (
|
||||
nextProps.selectedSource &&
|
||||
this.state.highlightItems &&
|
||||
this.state.highlightItems[0].name == "root"
|
||||
) {
|
||||
const highlightItems = getDirectories(
|
||||
nextProps.selectedSource,
|
||||
// Ensure querying latest state, in case updateTree updated the source tree
|
||||
this.state.sourceTree
|
||||
);
|
||||
this.setState({ highlightItems });
|
||||
}
|
||||
}
|
||||
|
||||
selectItem = item => {
|
||||
|
|
|
@ -34,8 +34,8 @@ add_task(async function() {
|
|||
await waitForPaused(dbg);
|
||||
await waitForSelectedSource(dbg, "content_script.js");
|
||||
|
||||
ok(
|
||||
findElementWithSelector(dbg, ".sources-list .focused"),
|
||||
await waitFor(
|
||||
() => findElementWithSelector(dbg, ".sources-list .focused"),
|
||||
"Source is focused"
|
||||
);
|
||||
assertPausedAtSourceAndLine(
|
||||
|
|
|
@ -393,19 +393,14 @@ add_task(async function testSourceTreeWithWebExtensionContentScript() {
|
|||
let dbg = await initDebugger("doc-content-script-sources.html");
|
||||
// Let some time for unexpected source to appear
|
||||
await wait(1000);
|
||||
// Bug 1761975 - While the content script doesn't show up,
|
||||
// the internals of WebExtension codebase appear in the debugger...
|
||||
await waitForSourcesInSourceTree(dbg, ["ExtensionContent.jsm"]);
|
||||
await waitForSourcesInSourceTree(dbg, []);
|
||||
await dbg.toolbox.closeToolbox();
|
||||
|
||||
info("With the chrome preference, the content script shows up");
|
||||
await pushPref("devtools.chrome.enabled", true);
|
||||
const toolbox = await openToolboxForTab(gBrowser.selectedTab, "jsdebugger");
|
||||
dbg = createDebuggerContext(toolbox);
|
||||
await waitForSourcesInSourceTree(dbg, [
|
||||
"content_script.js",
|
||||
"ExtensionContent.jsm",
|
||||
]);
|
||||
await waitForSourcesInSourceTree(dbg, ["content_script.js"]);
|
||||
await selectSource(dbg, "content_script.js");
|
||||
ok(
|
||||
findElementWithSelector(dbg, ".sources-list .focused"),
|
||||
|
@ -445,7 +440,6 @@ add_task(async function testSourceTreeNamesForWebExtensions() {
|
|||
"Test content script extension",
|
||||
"Test content script extension is labeled properly"
|
||||
);
|
||||
is(getLabel(dbg, 3), "resource://gre", "resource://gre is labeled properly");
|
||||
|
||||
await dbg.toolbox.closeToolbox();
|
||||
await extension.unload();
|
||||
|
|
|
@ -58,6 +58,11 @@ const MessageState = overrides =>
|
|||
// List of all the messages added to the console. Unlike other properties, this Map
|
||||
// will be mutated on state changes for performance reasons.
|
||||
mutableMessagesById: new Map(),
|
||||
// Array of message ids, in chronological order. We use a dedicated property to store
|
||||
// the order (instead of relying on the order of insertion in mutableMessagesById)
|
||||
// as we might receive messages that need to be inserted at a specific index. Doing
|
||||
// so on the Map can be costly, especially when the Map holds lots of messages.
|
||||
mutableMessagesOrder: [],
|
||||
// List of elements matching the selector of CSS Warning messages(populated
|
||||
// on-demand via the UI).
|
||||
cssMessagesMatchingElements: new Map(),
|
||||
|
@ -103,6 +108,7 @@ function cloneState(state) {
|
|||
warningGroupsById: new Map(state.warningGroupsById),
|
||||
// no need to mutate the properties below as they're not directly triggering re-render
|
||||
mutableMessagesById: state.mutableMessagesById,
|
||||
mutableMessagesOrder: state.mutableMessagesOrder,
|
||||
currentGroup: state.currentGroup,
|
||||
lastMessageId: state.lastMessageId,
|
||||
};
|
||||
|
@ -167,8 +173,6 @@ function addMessage(newMessage, state, filtersState, prefsState, uiState) {
|
|||
newMessage.indent = parentGroups.length;
|
||||
}
|
||||
|
||||
const removedIds = [];
|
||||
|
||||
// Check if the current message could be placed in a Warning Group.
|
||||
// This needs to be done before setting the new message in mutableMessagesById so we have a
|
||||
// proper message.
|
||||
|
@ -261,21 +265,25 @@ function addMessage(newMessage, state, filtersState, prefsState, uiState) {
|
|||
// If the new message isn't the "oldest" one, then we need to insert it at the right
|
||||
// position in the message map.
|
||||
if (isUnsorted) {
|
||||
const entries = Array.from(state.mutableMessagesById.entries());
|
||||
const newMessageIndex = entries.findIndex(
|
||||
entry => entry[1].timeStamp > addedMessage.timeStamp
|
||||
);
|
||||
// This shouldn't happen as `isUnsorted` would only be true if the last message is
|
||||
// younger than the added message.
|
||||
if (newMessageIndex === -1) {
|
||||
state.mutableMessagesById.set(addedMessage.id, addedMessage);
|
||||
} else {
|
||||
entries.splice(newMessageIndex, 0, [addedMessage.id, addedMessage]);
|
||||
state.mutableMessagesById = new Map(entries);
|
||||
let newMessageIndex = 0;
|
||||
// This is can be on a hot path, so we're not using `findIndex`, which could be slow.
|
||||
// Furthermore, there's a high chance the message beed to be inserted somewhere at the
|
||||
// end of the list, so we loop through mutableMessagesOrder in reverse order.
|
||||
for (let i = state.mutableMessagesOrder.length - 1; i >= 0; i--) {
|
||||
const message = state.mutableMessagesById.get(
|
||||
state.mutableMessagesOrder[i]
|
||||
);
|
||||
if (message.timeStamp <= addedMessage.timeStamp) {
|
||||
newMessageIndex = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
state.mutableMessagesOrder.splice(newMessageIndex, 0, addedMessage.id);
|
||||
} else {
|
||||
state.mutableMessagesById.set(addedMessage.id, addedMessage);
|
||||
state.mutableMessagesOrder.push(addedMessage.id);
|
||||
}
|
||||
state.mutableMessagesById.set(addedMessage.id, addedMessage);
|
||||
|
||||
if (newMessage.type === "trace") {
|
||||
// We want the stacktrace to be open by default.
|
||||
|
@ -322,16 +330,20 @@ function addMessage(newMessage, state, filtersState, prefsState, uiState) {
|
|||
} else if (isUnsorted) {
|
||||
// If the new message wasn't the "oldest" one, then we need to insert its id at
|
||||
// the right position in the array.
|
||||
const index = state.visibleMessages.findIndex(
|
||||
id => state.mutableMessagesById.get(id).timeStamp > newMessage.timeStamp
|
||||
);
|
||||
// If the index wasn't found, it means the new message is the oldest of the visible
|
||||
// messages, so we can directly push it into the array.
|
||||
if (index == -1) {
|
||||
state.visibleMessages.push(newMessage.id);
|
||||
} else {
|
||||
state.visibleMessages.splice(index, 0, newMessage.id);
|
||||
// This is can be on a hot path, so we're not using `findIndex`, which could be slow.
|
||||
// Furthermore, there's a high chance the message beed to be inserted somewhere at the
|
||||
// end of the list, so we loop through visibleMessages in reverse order.
|
||||
let index = 0;
|
||||
for (let i = state.visibleMessages.length - 1; i >= 0; i--) {
|
||||
const id = state.visibleMessages[i];
|
||||
if (
|
||||
state.mutableMessagesById.get(id).timeStamp <= newMessage.timeStamp
|
||||
) {
|
||||
index = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
state.visibleMessages.splice(index, 0, newMessage.id);
|
||||
} else {
|
||||
state.visibleMessages.push(newMessage.id);
|
||||
}
|
||||
|
@ -347,7 +359,7 @@ function addMessage(newMessage, state, filtersState, prefsState, uiState) {
|
|||
state.networkMessagesUpdateById[newMessage.actor] = newMessage;
|
||||
}
|
||||
|
||||
return removeMessagesFromState(state, removedIds);
|
||||
return state;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line complexity
|
||||
|
@ -465,7 +477,8 @@ function messages(
|
|||
if (isGroupType(currMessage.type) || isWarningGroup(currMessage)) {
|
||||
// We want to make its children visible
|
||||
const messagesToShow = [];
|
||||
for (const [id, message] of mutableMessagesById) {
|
||||
for (const id of state.mutableMessagesOrder) {
|
||||
const message = mutableMessagesById.get(id);
|
||||
if (
|
||||
!visibleMessages.includes(message.id) &&
|
||||
((isWarningGroup(currMessage) && !!getWarningGroupType(message)) ||
|
||||
|
@ -495,18 +508,6 @@ function messages(
|
|||
...visibleMessages.slice(insertIndex),
|
||||
];
|
||||
}
|
||||
|
||||
// If the current message is a network event, mark it as opened-once,
|
||||
// so HTTP details are not fetched again the next time the user
|
||||
// opens the log.
|
||||
if (currMessage.source == "network") {
|
||||
openState.mutableMessagesById = new Map(mutableMessagesById).set(
|
||||
action.id,
|
||||
{
|
||||
...currMessage,
|
||||
}
|
||||
);
|
||||
}
|
||||
return openState;
|
||||
|
||||
case constants.MESSAGE_CLOSE:
|
||||
|
@ -631,7 +632,8 @@ function messages(
|
|||
}
|
||||
|
||||
let needSort = false;
|
||||
for (const [msgId, message] of state.mutableMessagesById) {
|
||||
for (const msgId of state.mutableMessagesOrder) {
|
||||
const message = state.mutableMessagesById.get(msgId);
|
||||
const warningGroupType = getWarningGroupType(message);
|
||||
if (warningGroupType) {
|
||||
const warningGroupMessageId = getParentWarningGroupMessageId(message);
|
||||
|
@ -714,6 +716,7 @@ function setVisibleMessages({
|
|||
}) {
|
||||
const {
|
||||
mutableMessagesById,
|
||||
mutableMessagesOrder,
|
||||
visibleMessages,
|
||||
messagesUiById,
|
||||
} = messagesState;
|
||||
|
@ -722,7 +725,8 @@ function setVisibleMessages({
|
|||
const matchedGroups = new Set();
|
||||
const filtered = getDefaultFiltersCounter();
|
||||
|
||||
mutableMessagesById.forEach((message, msgId) => {
|
||||
mutableMessagesOrder.forEach(msgId => {
|
||||
const message = mutableMessagesById.get(msgId);
|
||||
const groupParentId = message.groupId;
|
||||
let hasMatchedAncestor = false;
|
||||
const ancestors = [];
|
||||
|
@ -877,7 +881,8 @@ function limitTopLevelMessageCount(newState, logLimit) {
|
|||
const removedMessagesId = [];
|
||||
|
||||
let cleaningGroup = false;
|
||||
for (const [id, message] of newState.mutableMessagesById) {
|
||||
for (const id of newState.mutableMessagesOrder) {
|
||||
const message = newState.mutableMessagesById.get(id);
|
||||
// If we were cleaning a group and the current message does not have
|
||||
// a groupId, we're done cleaning.
|
||||
if (cleaningGroup === true && !message.groupId) {
|
||||
|
@ -962,7 +967,13 @@ function removeMessagesFromState(state, removedMessagesIds) {
|
|||
return res;
|
||||
}, {});
|
||||
|
||||
removedMessagesIds.forEach(id => state.mutableMessagesById.delete(id));
|
||||
removedMessagesIds.forEach(id => {
|
||||
state.mutableMessagesById.delete(id);
|
||||
state.mutableMessagesOrder.splice(
|
||||
state.mutableMessagesOrder.indexOf(id),
|
||||
1
|
||||
);
|
||||
});
|
||||
|
||||
if (state.messagesUiById.find(isInRemovedId)) {
|
||||
state.messagesUiById = state.messagesUiById.filter(
|
||||
|
|
|
@ -81,8 +81,8 @@ function clonePacket(packet) {
|
|||
* @return {Message} - The message, or undefined if the index does not exists in the map.
|
||||
*/
|
||||
function getMessageAt(state, index) {
|
||||
const messages = getMutableMessagesById(state);
|
||||
return messages.get([...messages.keys()][index]);
|
||||
const messageMap = getMutableMessagesById(state);
|
||||
return messageMap.get(state.messages.mutableMessagesOrder[index]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -102,7 +102,7 @@ function getFirstMessage(state) {
|
|||
* @return {Message} - The last message, or undefined if there are no message in store.
|
||||
*/
|
||||
function getLastMessage(state) {
|
||||
const lastIndex = getMutableMessagesById(state).size - 1;
|
||||
const lastIndex = state.messages.mutableMessagesOrder.length - 1;
|
||||
return getMessageAt(state, lastIndex);
|
||||
}
|
||||
|
||||
|
|
|
@ -320,6 +320,7 @@ describe("Message reducer:", () => {
|
|||
expect(getAllCssMessagesMatchingElements(state).size).toBe(0);
|
||||
expect(getCurrentGroup(state)).toBe(null);
|
||||
expect(getAllRepeatById(state)).toEqual({});
|
||||
expect(state.messages.mutableMessagesOrder).toEqual([]);
|
||||
});
|
||||
|
||||
it("cleans the repeatsById object when messages are pruned", () => {
|
||||
|
@ -383,6 +384,9 @@ describe("Message reducer:", () => {
|
|||
expect(getLastMessage(getState()).parameters[0]).toBe(
|
||||
`message num ${logLimit + 2}`
|
||||
);
|
||||
|
||||
const { mutableMessagesOrder } = getState().messages;
|
||||
expect(mutableMessagesOrder.length).toBe(logLimit);
|
||||
});
|
||||
|
||||
it("properly limits number of messages when there are nested groups", () => {
|
||||
|
@ -421,9 +425,12 @@ describe("Message reducer:", () => {
|
|||
|
||||
const visibleMessages = getVisibleMessages(getState());
|
||||
const messages = getMutableMessagesById(getState());
|
||||
const { mutableMessagesOrder } = getState().messages;
|
||||
|
||||
expect(messages.size).toBe(logLimit);
|
||||
expect(visibleMessages.length).toBe(logLimit);
|
||||
expect(mutableMessagesOrder.length).toBe(logLimit);
|
||||
|
||||
expect(messages.get(visibleMessages[0]).parameters[0]).toBe(`message-0`);
|
||||
expect(messages.get(visibleMessages[logLimit - 1]).parameters[0]).toBe(
|
||||
`message-${logLimit - 1}`
|
||||
|
@ -648,6 +655,73 @@ describe("Message reducer:", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("mutableMessagesOrder", () => {
|
||||
it("adds a message to an empty store", () => {
|
||||
const { dispatch, getState } = setupStore();
|
||||
|
||||
const packet = stubPackets.get("console.log('foobar', 'test')");
|
||||
dispatch(actions.messagesAdd([packet]));
|
||||
|
||||
const { mutableMessagesOrder } = getState().messages;
|
||||
expect(mutableMessagesOrder.length).toBe(1);
|
||||
expect(mutableMessagesOrder[0]).toBe(
|
||||
// Don't get getMessageIndexAt/getFirstMessage since it relies on mutableMessagesOrder
|
||||
[...getMutableMessagesById(getState()).keys()][0]
|
||||
);
|
||||
});
|
||||
|
||||
it("reorder messages", () => {
|
||||
const { dispatch, getState } = setupStore();
|
||||
|
||||
const naNpacket = stubPackets.get("console.log(NaN)");
|
||||
dispatch(actions.messagesAdd([naNpacket]));
|
||||
|
||||
// Add a message that has a shorter timestamp than the previous one, and thus, should
|
||||
// be displayed before
|
||||
const nullPacket = clonePacket(stubPackets.get("console.log(null)"));
|
||||
nullPacket.message.timeStamp = naNpacket.message.timeStamp - 10;
|
||||
dispatch(actions.messagesAdd([nullPacket]));
|
||||
|
||||
// Add a message that should be display between the 2 previous messages
|
||||
const undefinedPacket = clonePacket(
|
||||
stubPackets.get("console.log(undefined)")
|
||||
);
|
||||
undefinedPacket.message.timeStamp = naNpacket.message.timeStamp - 5;
|
||||
dispatch(actions.messagesAdd([undefinedPacket]));
|
||||
|
||||
const { mutableMessagesOrder } = getState().messages;
|
||||
const [nanMessage, nullMessage, undefinedMessage] = [
|
||||
...getMutableMessagesById(getState()).values(),
|
||||
];
|
||||
const visibleMessages = getVisibleMessages(getState());
|
||||
|
||||
// Checking that messages in the Map are the expected ones
|
||||
expect(nanMessage.parameters[0].type).toBe("NaN");
|
||||
expect(nullMessage.parameters[0].type).toBe("null");
|
||||
expect(undefinedMessage.parameters[0].type).toBe("undefined");
|
||||
|
||||
// Check that mutableMessagesOrder has the message ids in the chronological order
|
||||
expect(mutableMessagesOrder).toEqual([
|
||||
nullMessage.id,
|
||||
undefinedMessage.id,
|
||||
nanMessage.id,
|
||||
]);
|
||||
|
||||
// Since we didn't filtered anything, visibleMessages should be similar to mutableMessagesOrder
|
||||
expect(mutableMessagesOrder).toEqual(visibleMessages);
|
||||
|
||||
// Check that visibleMessages is computed from mutableMessagesOrder when filtering
|
||||
dispatch(actions.filterToggle("log"));
|
||||
expect(getVisibleMessages(getState())).toEqual([]);
|
||||
dispatch(actions.filterToggle("log"));
|
||||
expect(getVisibleMessages(getState())).toEqual([
|
||||
nullMessage.id,
|
||||
undefinedMessage.id,
|
||||
nanMessage.id,
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("expandedMessageIds", () => {
|
||||
it("opens console.trace messages when they are added", () => {
|
||||
const { dispatch, getState } = setupStore();
|
||||
|
@ -1157,8 +1231,10 @@ describe("Message reducer:", () => {
|
|||
dispatch(actions.messageRemove(secondTraceMessage.id));
|
||||
|
||||
const messages = getMutableMessagesById(getState());
|
||||
const { mutableMessagesOrder } = getState().messages;
|
||||
// The messages was removed
|
||||
expect(messages.size).toBe(3);
|
||||
expect(mutableMessagesOrder.length).toBe(3);
|
||||
|
||||
// Its id was removed from the messagesUI property as well
|
||||
expanded = getAllMessagesUiById(getState());
|
||||
|
|
|
@ -2056,6 +2056,31 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
|
|||
this._shouldEmitNewSource = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Filtering function to filter out sources for which we don't want to notify/create
|
||||
* source actors
|
||||
*
|
||||
* @param {Debugger.Source} source
|
||||
* The source to accept or ignore
|
||||
* @param Boolean
|
||||
* True, if we want to create a source actor.
|
||||
*/
|
||||
_acceptSource(source) {
|
||||
// We have some spurious source created by ExtensionContent.jsm when debugging tabs.
|
||||
// These sources are internal stuff injected by WebExt codebase to implement content
|
||||
// scripts. We can't easily ignore them from Debugger API, so ignore them
|
||||
// when debugging a tab (i.e. browser-element). As we still want to debug them
|
||||
// from the browser toolbox.
|
||||
if (
|
||||
this._parent.sessionContext.type == "browser-element" &&
|
||||
source.url.endsWith("ExtensionContent.jsm")
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add the provided source to the server cache.
|
||||
*
|
||||
|
@ -2063,6 +2088,10 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
|
|||
* The source that will be stored.
|
||||
*/
|
||||
_addSource(source) {
|
||||
if (!this._acceptSource(source)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Preloaded WebExtension content scripts may be cached internally by
|
||||
// ExtensionContent.jsm and ThreadActor would ignore them on a page reload
|
||||
// because it finds them in the _debuggerSourcesSeen WeakSet,
|
||||
|
|
|
@ -23,6 +23,9 @@ const {
|
|||
} = require("devtools/shared/specs/targets/window-global");
|
||||
const { tabDescriptorSpec } = require("devtools/shared/specs/descriptors/tab");
|
||||
const Targets = require("devtools/server/actors/targets/index");
|
||||
const {
|
||||
createContentProcessSessionContext,
|
||||
} = require("devtools/server/actors/watcher/session-context");
|
||||
|
||||
var gTestGlobals = new Set();
|
||||
DevToolsServer.addTestGlobal = function(global) {
|
||||
|
@ -150,6 +153,8 @@ const TestTargetActor = protocol.ActorClassWithSpec(windowGlobalTargetSpec, {
|
|||
initialize: function(conn, global) {
|
||||
protocol.Actor.prototype.initialize.call(this, conn);
|
||||
this.conn = conn;
|
||||
|
||||
this.sessionContext = createContentProcessSessionContext();
|
||||
this._global = global;
|
||||
this._global.wrappedJSObject = global;
|
||||
this.threadActor = new ThreadActor(this, this._global);
|
||||
|
|
|
@ -49,6 +49,7 @@ The plugin implements the following rules:
|
|||
eslint-plugin-mozilla/reject-addtask-only
|
||||
eslint-plugin-mozilla/reject-chromeutils-import-params
|
||||
eslint-plugin-mozilla/reject-global-this
|
||||
eslint-plugin-mozilla/reject-globalThis-modification
|
||||
eslint-plugin-mozilla/reject-importGlobalProperties
|
||||
eslint-plugin-mozilla/reject-osfile
|
||||
eslint-plugin-mozilla/reject-relative-requires
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
reject-globalThis-modification
|
||||
==============================
|
||||
|
||||
Reject any modification to ``globalThis`` inside the system modules.
|
||||
|
||||
``globalThis`` is the shared global inside the system modules, and modification
|
||||
on it is visible from all modules, and it shouldn't be done unless it's really
|
||||
necessary.
|
||||
|
||||
Examples of incorrect code for this rule:
|
||||
-----------------------------------------
|
||||
|
||||
.. code-block:: js
|
||||
|
||||
globalThis.foo = 10;
|
||||
Object.defineProperty(globalThis, "bar", { value: 20});
|
||||
XPCOMUtils.defineLazyModuleGetters(globalThis, {
|
||||
Services: "resource://gre/modules/Services.jsm",
|
||||
});
|
|
@ -5796,8 +5796,8 @@ nsDocShell::OnStateChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
|
|||
if (WindowContext* windowContext =
|
||||
mBrowsingContext->GetCurrentWindowContext()) {
|
||||
SessionStoreChild::From(windowContext->GetWindowGlobalChild())
|
||||
->SendResetSessionStore(
|
||||
mBrowsingContext, mBrowsingContext->GetSessionStoreEpoch());
|
||||
->ResetSessionStore(mBrowsingContext,
|
||||
mBrowsingContext->GetSessionStoreEpoch());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6538,11 +6538,14 @@ nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
|
|||
if constexpr (SessionStoreUtils::NATIVE_LISTENER) {
|
||||
if (WindowContext* windowContext =
|
||||
mBrowsingContext->GetCurrentWindowContext()) {
|
||||
// TODO(farre): File bug: From a user perspective this would probably be
|
||||
// just fine to run off the change listener timer. Turns out that a flush
|
||||
// is needed. Several tests depend on this behaviour. Could potentially be
|
||||
// an optimization for later. See Bug 1756995.
|
||||
SessionStoreChangeListener::FlushAllSessionStoreData(windowContext);
|
||||
using Change = SessionStoreChangeListener::Change;
|
||||
|
||||
// We've finished loading the page and now we want to collect all the
|
||||
// session store state that the page is initialized with.
|
||||
SessionStoreChangeListener::CollectSessionStoreData(
|
||||
windowContext,
|
||||
EnumSet<Change>(Change::Input, Change::Scroll, Change::SessionHistory,
|
||||
Change::WireFrame));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11463,6 +11466,7 @@ nsresult nsDocShell::UpdateURLAndHistory(Document* aDocument, nsIURI* aNewURI,
|
|||
UpdateActiveEntry(false,
|
||||
/* aPreviousScrollPos = */ Some(scrollPos), aNewURI,
|
||||
/* aOriginalURI = */ nullptr,
|
||||
/* aReferrerInfo = */ nullptr,
|
||||
/* aTriggeringPrincipal = */ aDocument->NodePrincipal(),
|
||||
csp, title, scrollRestorationIsManual, aData,
|
||||
uriWasModified);
|
||||
|
@ -11505,12 +11509,17 @@ nsresult nsDocShell::UpdateURLAndHistory(Document* aDocument, nsIURI* aNewURI,
|
|||
// in our case. We could also set it to aNewURI, with the same result.
|
||||
// We don't use aTitle here, see bug 544535.
|
||||
nsString title;
|
||||
nsCOMPtr<nsIReferrerInfo> referrerInfo;
|
||||
if (mActiveEntry) {
|
||||
title = mActiveEntry->GetTitle();
|
||||
referrerInfo = mActiveEntry->GetReferrerInfo();
|
||||
} else {
|
||||
referrerInfo = nullptr;
|
||||
}
|
||||
UpdateActiveEntry(
|
||||
true, /* aPreviousScrollPos = */ Nothing(), aNewURI, aNewURI,
|
||||
aDocument->NodePrincipal(), aDocument->GetCsp(), title,
|
||||
/* aReferrerInfo = */ referrerInfo, aDocument->NodePrincipal(),
|
||||
aDocument->GetCsp(), title,
|
||||
mActiveEntry && mActiveEntry->GetScrollRestorationIsManual(), aData,
|
||||
uriWasModified);
|
||||
} else {
|
||||
|
@ -11930,10 +11939,10 @@ nsresult nsDocShell::AddToSessionHistory(
|
|||
|
||||
void nsDocShell::UpdateActiveEntry(
|
||||
bool aReplace, const Maybe<nsPoint>& aPreviousScrollPos, nsIURI* aURI,
|
||||
nsIURI* aOriginalURI, nsIPrincipal* aTriggeringPrincipal,
|
||||
nsIContentSecurityPolicy* aCsp, const nsAString& aTitle,
|
||||
bool aScrollRestorationIsManual, nsIStructuredCloneContainer* aData,
|
||||
bool aURIWasModified) {
|
||||
nsIURI* aOriginalURI, nsIReferrerInfo* aReferrerInfo,
|
||||
nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp,
|
||||
const nsAString& aTitle, bool aScrollRestorationIsManual,
|
||||
nsIStructuredCloneContainer* aData, bool aURIWasModified) {
|
||||
MOZ_ASSERT(mozilla::SessionHistoryInParent());
|
||||
MOZ_ASSERT(aURI, "uri is null");
|
||||
MOZ_ASSERT(mLoadType == LOAD_PUSHSTATE,
|
||||
|
@ -11962,6 +11971,7 @@ void nsDocShell::UpdateActiveEntry(
|
|||
aURI, aTriggeringPrincipal, nullptr, nullptr, aCsp, mContentTypeHint);
|
||||
}
|
||||
mActiveEntry->SetOriginalURI(aOriginalURI);
|
||||
mActiveEntry->SetReferrerInfo(aReferrerInfo);
|
||||
mActiveEntry->SetTitle(aTitle);
|
||||
mActiveEntry->SetStateData(static_cast<nsStructuredCloneContainer*>(aData));
|
||||
mActiveEntry->SetURIWasModified(aURIWasModified);
|
||||
|
|
|
@ -640,10 +640,10 @@ class nsDocShell final : public nsDocLoader,
|
|||
|
||||
void UpdateActiveEntry(
|
||||
bool aReplace, const mozilla::Maybe<nsPoint>& aPreviousScrollPos,
|
||||
nsIURI* aURI, nsIURI* aOriginalURI, nsIPrincipal* aTriggeringPrincipal,
|
||||
nsIContentSecurityPolicy* aCsp, const nsAString& aTitle,
|
||||
bool aScrollRestorationIsManual, nsIStructuredCloneContainer* aData,
|
||||
bool aURIWasModified);
|
||||
nsIURI* aURI, nsIURI* aOriginalURI, nsIReferrerInfo* aReferrerInfo,
|
||||
nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp,
|
||||
const nsAString& aTitle, bool aScrollRestorationIsManual,
|
||||
nsIStructuredCloneContainer* aData, bool aURIWasModified);
|
||||
|
||||
nsresult AddChildSHEntry(nsISHEntry* aCloneRef, nsISHEntry* aNewEntry,
|
||||
int32_t aChildOffset, uint32_t aLoadType,
|
||||
|
|
|
@ -71,6 +71,11 @@ class SessionHistoryInfo {
|
|||
mResultPrincipalURI = aResultPrincipalURI;
|
||||
}
|
||||
|
||||
nsIReferrerInfo* GetReferrerInfo() { return mReferrerInfo; }
|
||||
void SetReferrerInfo(nsIReferrerInfo* aReferrerInfo) {
|
||||
mReferrerInfo = aReferrerInfo;
|
||||
}
|
||||
|
||||
bool HasPostData() const { return mPostData; }
|
||||
already_AddRefed<nsIInputStream> GetPostData() const;
|
||||
void SetPostData(nsIInputStream* aPostData);
|
||||
|
|
13
docshell/test/mochitest/file_bug1773192_1.html
Normal file
13
docshell/test/mochitest/file_bug1773192_1.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<script>
|
||||
let bc = new BroadcastChannel("bug1743353");
|
||||
bc.addEventListener("message", ({ data }) => {
|
||||
if (data == "next") {
|
||||
location = "file_bug1773192_2.html";
|
||||
} else if (data == "close") {
|
||||
window.close();
|
||||
}
|
||||
});
|
||||
window.addEventListener("pageshow", () => {
|
||||
bc.postMessage({ location: location.href, referrer: document.referrer });
|
||||
});
|
||||
</script>
|
13
docshell/test/mochitest/file_bug1773192_2.html
Normal file
13
docshell/test/mochitest/file_bug1773192_2.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Cache-Control" content="no-cache, no-store">
|
||||
<meta name="referrer" content="same-origin">
|
||||
</head>
|
||||
<body>
|
||||
<form method="POST" action="file_bug1773192_3.sjs"></form>
|
||||
<script>
|
||||
history.replaceState({}, "", document.referrer);
|
||||
document.forms[0].submit();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
3
docshell/test/mochitest/file_bug1773192_3.sjs
Normal file
3
docshell/test/mochitest/file_bug1773192_3.sjs
Normal file
|
@ -0,0 +1,3 @@
|
|||
function handleRequest(request, response) {
|
||||
response.write("<script>history.back();</script>");
|
||||
}
|
|
@ -140,6 +140,11 @@ support-files =
|
|||
[test_bug1747033.html]
|
||||
support-files =
|
||||
file_bug1747033.sjs
|
||||
[test_bug1773192.html]
|
||||
support-files =
|
||||
file_bug1773192_1.html
|
||||
file_bug1773192_2.html
|
||||
file_bug1773192_3.sjs
|
||||
[test_close_onpagehide_by_history_back.html]
|
||||
[test_close_onpagehide_by_window_close.html]
|
||||
[test_compressed_multipart.html]
|
||||
|
|
61
docshell/test/mochitest/test_bug1773192.html
Normal file
61
docshell/test/mochitest/test_bug1773192.html
Normal file
|
@ -0,0 +1,61 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test referrer with going back</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
|
||||
<script>
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// file_bug1773192_1.html will send a message with some data on pageshow.
|
||||
function waitForData(bc) {
|
||||
return new Promise(resolve => {
|
||||
bc.addEventListener(
|
||||
"message",
|
||||
({ data }) => {
|
||||
resolve(data);
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
});
|
||||
}
|
||||
async function runTest() {
|
||||
let bc = new BroadcastChannel("bug1743353");
|
||||
|
||||
let getData = waitForData(bc);
|
||||
|
||||
window.open("file_bug1773192_1.html", "", "noreferrer");
|
||||
|
||||
await getData.then(({ referrer }) => {
|
||||
is(referrer, "", "Referrer should be empty at first.");
|
||||
});
|
||||
|
||||
getData = waitForData(bc);
|
||||
|
||||
// When file_bug1773192_1.html receives this message it will navigate to
|
||||
// file_bug1773192_2.html. file_bug1773192_2.html removes itself from
|
||||
// history with replaceState and submits a form with the POST method to
|
||||
// file_bug1773192_3.sjs. file_bug1773192_3.sjs goes back in history.
|
||||
// We should end up back at file_bug1773192_1.html, which will send a
|
||||
// message with some data on pageshow.
|
||||
bc.postMessage("next");
|
||||
|
||||
await getData.then(({ location, referrer }) => {
|
||||
let firstURL = new URL("file_bug1773192_1.html", location).toString();
|
||||
is(location, firstURL, "Location should be the first page again.");
|
||||
is(referrer, firstURL, "Referrer should also be the first page.");
|
||||
});
|
||||
|
||||
bc.postMessage("close");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="runTest();">
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test"></pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1442,7 +1442,6 @@ Document::Document(const char* aContentType)
|
|||
mViewportFit(ViewportFitType::Auto),
|
||||
mSubDocuments(nullptr),
|
||||
mHeaderData(nullptr),
|
||||
mFlashClassification(FlashClassification::Unknown),
|
||||
mServoRestyleRootDirtyBits(0),
|
||||
mThrowOnDynamicMarkupInsertionCounter(0),
|
||||
mIgnoreOpensDuringUnloadCounter(0),
|
||||
|
@ -4302,11 +4301,6 @@ bool Document::GetAllowPlugins() {
|
|||
}
|
||||
}
|
||||
|
||||
FlashClassification classification = DocumentFlashClassification();
|
||||
if (classification == FlashClassification::Denied) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -16610,52 +16604,6 @@ bool Document::IsExtensionPage() const {
|
|||
BasePrincipal::Cast(NodePrincipal())->AddonPolicy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the classification of the Flash plugins in the document based on
|
||||
* the classification lists. For more information, see
|
||||
* toolkit/components/url-classifier/flash-block-lists.rst
|
||||
*/
|
||||
FlashClassification Document::DocumentFlashClassification() {
|
||||
// Disable flash blocking when fission is enabled(See Bug 1584931).
|
||||
const auto fnIsFlashBlockingEnabled = [] {
|
||||
return StaticPrefs::plugins_flashBlock_enabled() && !FissionAutostart();
|
||||
};
|
||||
|
||||
// If neither pref is on, skip the null-principal and principal URI checks.
|
||||
if (!StaticPrefs::plugins_http_https_only() && !fnIsFlashBlockingEnabled()) {
|
||||
return FlashClassification::Unknown;
|
||||
}
|
||||
|
||||
if (!NodePrincipal()->GetIsContentPrincipal()) {
|
||||
return FlashClassification::Denied;
|
||||
}
|
||||
|
||||
if (StaticPrefs::plugins_http_https_only()) {
|
||||
// Only allow plugins for documents from an HTTP/HTTPS origin. This should
|
||||
// allow dependent data: URIs to load plugins, but not:
|
||||
// * chrome documents
|
||||
// * "bare" data: loads
|
||||
// * FTP/gopher/file
|
||||
|
||||
if (!(NodePrincipal()->SchemeIs("http") ||
|
||||
NodePrincipal()->SchemeIs("https"))) {
|
||||
return FlashClassification::Denied;
|
||||
}
|
||||
}
|
||||
|
||||
// If flash blocking is disabled, it is equivalent to all sites being
|
||||
// on neither list.
|
||||
if (!fnIsFlashBlockingEnabled()) {
|
||||
return FlashClassification::Unknown;
|
||||
}
|
||||
|
||||
if (mFlashClassification == FlashClassification::Unknown) {
|
||||
mFlashClassification = DocumentFlashClassificationInternal();
|
||||
}
|
||||
|
||||
return mFlashClassification;
|
||||
}
|
||||
|
||||
void Document::AddResizeObserver(ResizeObserver& aObserver) {
|
||||
if (!mResizeObserverController) {
|
||||
mResizeObserverController = MakeUnique<ResizeObserverController>(this);
|
||||
|
@ -16692,123 +16640,6 @@ void Document::ScheduleResizeObserversNotification() const {
|
|||
mResizeObserverController->ScheduleNotification();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes |mIsThirdPartyForFlashClassifier| if necessary and returns its
|
||||
* value. The value returned represents whether this document should be
|
||||
* considered Third-Party.
|
||||
*
|
||||
* A top-level document cannot be a considered Third-Party; only subdocuments
|
||||
* may. For a subdocument to be considered Third-Party, it must meet ANY ONE
|
||||
* of the following requirements:
|
||||
* - The document's parent is Third-Party
|
||||
* - The document has a different scheme (http/https) than its parent document
|
||||
* - The document's domain and subdomain do not match those of its parent
|
||||
* document.
|
||||
*
|
||||
* If there is an error in determining whether the document is Third-Party,
|
||||
* it will be assumed to be Third-Party for security reasons.
|
||||
*/
|
||||
bool Document::IsThirdPartyForFlashClassifier() {
|
||||
if (mIsThirdPartyForFlashClassifier.isSome()) {
|
||||
return mIsThirdPartyForFlashClassifier.value();
|
||||
}
|
||||
|
||||
BrowsingContext* browsingContext = this->GetBrowsingContext();
|
||||
if (!browsingContext) {
|
||||
mIsThirdPartyForFlashClassifier.emplace(true);
|
||||
return mIsThirdPartyForFlashClassifier.value();
|
||||
}
|
||||
|
||||
if (browsingContext->IsTop()) {
|
||||
mIsThirdPartyForFlashClassifier.emplace(false);
|
||||
return mIsThirdPartyForFlashClassifier.value();
|
||||
}
|
||||
|
||||
nsCOMPtr<Document> parentDocument = GetInProcessParentDocument();
|
||||
if (!parentDocument) {
|
||||
// Failure
|
||||
mIsThirdPartyForFlashClassifier.emplace(true);
|
||||
return mIsThirdPartyForFlashClassifier.value();
|
||||
}
|
||||
|
||||
if (parentDocument->IsThirdPartyForFlashClassifier()) {
|
||||
mIsThirdPartyForFlashClassifier.emplace(true);
|
||||
return mIsThirdPartyForFlashClassifier.value();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = NodePrincipal();
|
||||
nsCOMPtr<nsIPrincipal> parentPrincipal = parentDocument->GetPrincipal();
|
||||
|
||||
bool principalsMatch = false;
|
||||
nsresult rv = principal->Equals(parentPrincipal, &principalsMatch);
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
// Failure
|
||||
mIsThirdPartyForFlashClassifier.emplace(true);
|
||||
return mIsThirdPartyForFlashClassifier.value();
|
||||
}
|
||||
|
||||
if (!principalsMatch) {
|
||||
mIsThirdPartyForFlashClassifier.emplace(true);
|
||||
return mIsThirdPartyForFlashClassifier.value();
|
||||
}
|
||||
|
||||
// Fall-through. Document is not a Third-Party Document.
|
||||
mIsThirdPartyForFlashClassifier.emplace(false);
|
||||
return mIsThirdPartyForFlashClassifier.value();
|
||||
}
|
||||
|
||||
FlashClassification Document::DocumentFlashClassificationInternal() {
|
||||
FlashClassification classification = FlashClassification::Unknown;
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(GetChannel());
|
||||
if (httpChannel) {
|
||||
nsIHttpChannel::FlashPluginState state = nsIHttpChannel::FlashPluginUnknown;
|
||||
httpChannel->GetFlashPluginState(&state);
|
||||
|
||||
// Allow unknown children to inherit allowed status from parent, but do not
|
||||
// allow denied children to do so.
|
||||
|
||||
if (state == nsIHttpChannel::FlashPluginDeniedInSubdocuments &&
|
||||
IsThirdPartyForFlashClassifier()) {
|
||||
return FlashClassification::Denied;
|
||||
}
|
||||
|
||||
if (state == nsIHttpChannel::FlashPluginDenied) {
|
||||
return FlashClassification::Denied;
|
||||
}
|
||||
|
||||
if (state == nsIHttpChannel::FlashPluginAllowed) {
|
||||
classification = FlashClassification::Allowed;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsTopLevelContentDocument()) {
|
||||
return classification;
|
||||
}
|
||||
|
||||
Document* parentDocument = GetInProcessParentDocument();
|
||||
if (!parentDocument) {
|
||||
return FlashClassification::Denied;
|
||||
}
|
||||
|
||||
FlashClassification parentClassification =
|
||||
parentDocument->DocumentFlashClassification();
|
||||
|
||||
if (parentClassification == FlashClassification::Denied) {
|
||||
return FlashClassification::Denied;
|
||||
}
|
||||
|
||||
// Allow unknown children to inherit allowed status from parent, but
|
||||
// do not allow denied children to do so.
|
||||
if (classification == FlashClassification::Unknown &&
|
||||
parentClassification == FlashClassification::Allowed) {
|
||||
return FlashClassification::Allowed;
|
||||
}
|
||||
|
||||
return classification;
|
||||
}
|
||||
|
||||
void Document::ClearStaleServoData() {
|
||||
DocumentStyleRootIterator iter(this);
|
||||
while (Element* root = iter.GetNextStyleRoot()) {
|
||||
|
|
|
@ -3757,10 +3757,6 @@ class Document : public nsINode,
|
|||
// determine if it belongs to a tracker.
|
||||
bool IsScriptTracking(JSContext* aCx) const;
|
||||
|
||||
// For more information on Flash classification, see
|
||||
// toolkit/components/url-classifier/flash-block-lists.rst
|
||||
FlashClassification DocumentFlashClassification();
|
||||
|
||||
// ResizeObserver usage.
|
||||
void AddResizeObserver(ResizeObserver&);
|
||||
void RemoveResizeObserver(ResizeObserver&);
|
||||
|
@ -3886,11 +3882,7 @@ class Document : public nsINode,
|
|||
// stored in parent iframe or container's browsingContext (cross process)
|
||||
already_AddRefed<mozilla::dom::FeaturePolicy> GetParentFeaturePolicy();
|
||||
|
||||
FlashClassification DocumentFlashClassificationInternal();
|
||||
|
||||
public:
|
||||
bool IsThirdPartyForFlashClassifier();
|
||||
|
||||
const OriginTrials& Trials() const { return mTrials; }
|
||||
|
||||
private:
|
||||
|
@ -5089,14 +5081,6 @@ class Document : public nsINode,
|
|||
class HeaderData;
|
||||
UniquePtr<HeaderData> mHeaderData;
|
||||
|
||||
// For determining if this is a flash document which should be
|
||||
// blocked based on its principal.
|
||||
FlashClassification mFlashClassification;
|
||||
|
||||
// Do not use this value directly. Call the |IsThirdPartyForFlashClassifier()|
|
||||
// method, which caches its result here.
|
||||
Maybe<bool> mIsThirdPartyForFlashClassifier;
|
||||
|
||||
nsRevocableEventPtr<nsRunnableMethod<Document, void, false>>
|
||||
mPendingTitleChangeEvent;
|
||||
|
||||
|
|
|
@ -16,8 +16,6 @@ if (DEBUG) {
|
|||
|
||||
var EXPORTED_SYMBOLS = ["IndexedDBHelper"];
|
||||
|
||||
Cu.importGlobalProperties(["indexedDB"]);
|
||||
|
||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function getErrorName(err) {
|
||||
|
|
|
@ -185,4 +185,11 @@ RefPtr<GenericPromise> ClientHandle::OnDetach() {
|
|||
return mDetachPromise;
|
||||
}
|
||||
|
||||
void ClientHandle::EvictFromBFCache() {
|
||||
ClientEvictBFCacheArgs args;
|
||||
StartOp(
|
||||
std::move(args), [](const ClientOpResult& aResult) {},
|
||||
[](const ClientOpResult& aResult) {});
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue