mirror of
https://github.com/Feodor2/Mypal68.git
synced 2025-06-18 14:55:44 -04:00
68.13.9 - everything else
This commit is contained in:
parent
8ed7e5e7f4
commit
31cef1d61c
@ -59,7 +59,6 @@ xpcom/reflect/xptcall/md/unix/.*
|
||||
# awk '{print ""$1".*"}' ./tools/rewriting/ThirdPartyPaths.txt
|
||||
browser/components/translation/cld2/.*
|
||||
browser/extensions/mortar/ppapi/.*
|
||||
db/sqlite3/src/.*
|
||||
devtools/client/shared/sourceeditor/codemirror/.*
|
||||
devtools/client/shared/sourceeditor/tern/.*
|
||||
dom/canvas/test/webgl-conf/checkout/closure-library/.*
|
||||
|
17
.eslintrc.js
17
.eslintrc.js
@ -145,23 +145,6 @@ module.exports = {
|
||||
"no-redeclare": "off",
|
||||
"no-global-assign": "off",
|
||||
}
|
||||
}, {
|
||||
"files": [
|
||||
"image/**",
|
||||
],
|
||||
"rules": {
|
||||
"mozilla/consistent-if-bracing": "off",
|
||||
"mozilla/use-chromeutils-generateqi": "off",
|
||||
"mozilla/use-services": "off",
|
||||
"no-array-constructor": "off",
|
||||
"no-implied-eval": "off",
|
||||
"no-redeclare": "off",
|
||||
"no-self-assign": "off",
|
||||
"no-throw-literal": "off",
|
||||
"no-undef": "off",
|
||||
"no-unneeded-ternary": "off",
|
||||
"no-unused-vars": "off",
|
||||
}
|
||||
}, {
|
||||
"files": [
|
||||
"netwerk/cookie/test/browser/**",
|
||||
|
2
CLOBBER
2
CLOBBER
@ -22,4 +22,4 @@
|
||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 1632434 - Update to ICU 67 requires clobber
|
||||
Bug 1551084 - Part 2. Make QCMS transform files use C++. r=miko
|
||||
|
521
Cargo.lock
generated
521
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -35,7 +35,6 @@ exclude = [
|
||||
"gfx/webrender_bindings",
|
||||
"media/mp4parse-rust/mp4parse",
|
||||
"media/mp4parse-rust/mp4parse_capi",
|
||||
"media/mp4parse-rust/mp4parse_fallible",
|
||||
"xpcom/rust/gkrust_utils",
|
||||
]
|
||||
|
||||
|
@ -117,7 +117,7 @@ void DocAccessibleWrap::CacheViewportCallback(nsITimer* aTimer,
|
||||
if (inViewAccs.Contains(acc->UniqueID())) {
|
||||
break;
|
||||
}
|
||||
inViewAccs.Put(acc->UniqueID(), acc);
|
||||
inViewAccs.Put(acc->UniqueID(), RefPtr{acc});
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,7 +213,7 @@ void DocAccessibleWrap::CacheFocusPath(AccessibleWrap* aAccessible) {
|
||||
acc->ActionCount(), name, textValue, nodeID, description,
|
||||
acc->CurValue(), acc->MinValue(), acc->MaxValue(),
|
||||
acc->Step(), attributes));
|
||||
mFocusPath.Put(acc->UniqueID(), acc);
|
||||
mFocusPath.Put(acc->UniqueID(), RefPtr{acc});
|
||||
}
|
||||
|
||||
ipcDoc->SendBatch(eBatch_FocusPath, cacheData);
|
||||
@ -223,7 +223,7 @@ void DocAccessibleWrap::CacheFocusPath(AccessibleWrap* aAccessible) {
|
||||
for (AccessibleWrap* acc = aAccessible; acc && acc != this->Parent();
|
||||
acc = static_cast<AccessibleWrap*>(acc->Parent())) {
|
||||
accessibles.AppendElement(acc);
|
||||
mFocusPath.Put(acc->UniqueID(), acc);
|
||||
mFocusPath.Put(acc->UniqueID(), RefPtr{acc});
|
||||
}
|
||||
|
||||
sessionAcc->ReplaceFocusPathCache(accessibles);
|
||||
|
@ -186,7 +186,7 @@ class AccessibleNode : public nsISupports, public nsWrapperCache {
|
||||
if (!aValue) {
|
||||
mRelationProperties.Remove(static_cast<int>(aProperty));
|
||||
} else {
|
||||
mRelationProperties.Put(static_cast<int>(aProperty), aValue);
|
||||
mRelationProperties.Put(static_cast<int>(aProperty), RefPtr{aValue});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,8 +9,8 @@
|
||||
#include "xpcAccEvents.h"
|
||||
#include "States.h"
|
||||
|
||||
#include "mozilla/EventStateManager.h"
|
||||
#include "mozilla/dom/Selection.h"
|
||||
#include "mozilla/dom/UserActivation.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
@ -30,7 +30,7 @@ AccEvent::AccEvent(uint32_t aEventType, Accessible* aAccessible,
|
||||
EIsFromUserInput aIsFromUserInput, EEventRule aEventRule)
|
||||
: mEventType(aEventType), mEventRule(aEventRule), mAccessible(aAccessible) {
|
||||
if (aIsFromUserInput == eAutoDetect)
|
||||
mIsFromUserInput = EventStateManager::IsHandlingUserInput();
|
||||
mIsFromUserInput = dom::UserActivation::IsHandlingUserInput();
|
||||
else
|
||||
mIsFromUserInput = aIsFromUserInput == eFromUserInput ? true : false;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ namespace a11y {
|
||||
*/
|
||||
class AccGroupInfo {
|
||||
public:
|
||||
~AccGroupInfo() { MOZ_COUNT_DTOR(AccGroupInfo); }
|
||||
MOZ_COUNTED_DTOR(AccGroupInfo)
|
||||
|
||||
/**
|
||||
* Return 1-based position in the group.
|
||||
|
@ -125,7 +125,7 @@ xpcAccessibleDocument* DocManager::GetXPCDocument(DocAccessible* aDocument) {
|
||||
xpcAccessibleDocument* xpcDoc = mXPCDocumentCache.GetWeak(aDocument);
|
||||
if (!xpcDoc) {
|
||||
xpcDoc = new xpcAccessibleDocument(aDocument);
|
||||
mXPCDocumentCache.Put(aDocument, xpcDoc);
|
||||
mXPCDocumentCache.Put(aDocument, RefPtr{xpcDoc});
|
||||
}
|
||||
return xpcDoc;
|
||||
}
|
||||
@ -144,7 +144,7 @@ xpcAccessibleDocument* DocManager::GetXPCDocument(DocAccessibleParent* aDoc) {
|
||||
|
||||
doc = new xpcAccessibleDocument(aDoc,
|
||||
Interfaces::DOCUMENT | Interfaces::HYPERTEXT);
|
||||
sRemoteXPCDocumentCache->Put(aDoc, doc);
|
||||
sRemoteXPCDocumentCache->Put(aDoc, RefPtr{doc});
|
||||
|
||||
return doc;
|
||||
}
|
||||
@ -458,7 +458,7 @@ DocAccessible* DocManager::CreateDocOrRootAccessible(Document* aDocument) {
|
||||
: new DocAccessibleWrap(aDocument, presShell);
|
||||
|
||||
// Cache the document accessible into document cache.
|
||||
mDocAccessibleCache.Put(aDocument, docAcc);
|
||||
mDocAccessibleCache.Put(aDocument, RefPtr{docAcc});
|
||||
|
||||
// Initialize the document accessible.
|
||||
docAcc->Init();
|
||||
|
@ -30,7 +30,9 @@ bool EventQueue::PushEvent(AccEvent* aEvent) {
|
||||
aEvent->Document() == mDocument,
|
||||
"Queued event belongs to another document!");
|
||||
|
||||
if (!mEvents.AppendElement(aEvent)) return false;
|
||||
// XXX(Bug 1631371) Check if this should use a fallible operation as it
|
||||
// pretended earlier, or change the return type to void.
|
||||
mEvents.AppendElement(aEvent);
|
||||
|
||||
// Filter events.
|
||||
CoalesceEvents();
|
||||
|
@ -119,7 +119,7 @@ static void LogDocShellTree(dom::Document* aDocumentNode) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
|
||||
treeItem->GetInProcessParent(getter_AddRefs(parentTreeItem));
|
||||
nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
|
||||
treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
|
||||
treeItem->GetInProcessRootTreeItem(getter_AddRefs(rootTreeItem));
|
||||
printf("docshell hierarchy, parent: %p, root: %p, is tab document: %s;",
|
||||
static_cast<void*>(parentTreeItem), static_cast<void*>(rootTreeItem),
|
||||
(nsCoreUtils::IsTabDocument(aDocumentNode) ? "yes" : "no"));
|
||||
|
@ -392,7 +392,7 @@ MARKUPMAP(
|
||||
[](Element* aElement, Accessible* aContext) -> Accessible* {
|
||||
return new HTMLOutputAccessible(aElement, aContext->Document());
|
||||
},
|
||||
roles::SECTION, Attr(live, polite))
|
||||
roles::STATUSBAR, Attr(live, polite))
|
||||
|
||||
MARKUPMAP(p, nullptr, roles::PARAGRAPH)
|
||||
|
||||
|
@ -948,7 +948,7 @@ void NotificationController::EventMap::PutEvent(AccTreeMutationEvent* aEvent) {
|
||||
uint64_t addr = reinterpret_cast<uintptr_t>(aEvent->GetAccessible());
|
||||
MOZ_ASSERT((addr & 0x3) == 0, "accessible is not 4 byte aligned");
|
||||
addr |= type;
|
||||
mTable.Put(addr, aEvent);
|
||||
mTable.Put(addr, RefPtr{aEvent});
|
||||
}
|
||||
|
||||
AccTreeMutationEvent* NotificationController::EventMap::GetEvent(
|
||||
|
@ -197,7 +197,10 @@ class NotificationController final : public EventQueue,
|
||||
* Pend an accessible subtree relocation.
|
||||
*/
|
||||
void ScheduleRelocation(Accessible* aOwner) {
|
||||
if (!mRelocations.Contains(aOwner) && mRelocations.AppendElement(aOwner)) {
|
||||
if (!mRelocations.Contains(aOwner)) {
|
||||
// XXX(Bug 1631371) Check if this should use a fallible operation as it
|
||||
// pretended earlier, or change the return type to void.
|
||||
mRelocations.AppendElement(aOwner);
|
||||
ScheduleProcessing();
|
||||
}
|
||||
}
|
||||
@ -233,8 +236,12 @@ class NotificationController final : public EventQueue,
|
||||
|
||||
RefPtr<Notification> notification =
|
||||
new TNotification<Class, Args...>(aInstance, aMethod, aArgs...);
|
||||
if (notification && mNotifications.AppendElement(notification))
|
||||
if (notification) {
|
||||
// XXX(Bug 1631371) Check if this should use a fallible operation as it
|
||||
// pretended earlier.
|
||||
mNotifications.AppendElement(notification);
|
||||
ScheduleProcessing();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -248,8 +255,12 @@ class NotificationController final : public EventQueue,
|
||||
Class* aInstance, typename TNotification<Class>::Callback aMethod) {
|
||||
RefPtr<Notification> notification =
|
||||
new TNotification<Class>(aInstance, aMethod);
|
||||
if (notification && mNotifications.AppendElement(notification))
|
||||
if (notification) {
|
||||
// XXX(Bug 1631371) Check if this should use a fallible operation as it
|
||||
// pretended earlier.
|
||||
mNotifications.AppendElement(notification);
|
||||
ScheduleProcessing();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Class, class Arg>
|
||||
@ -258,7 +269,10 @@ class NotificationController final : public EventQueue,
|
||||
Arg* aArg) {
|
||||
RefPtr<Notification> notification =
|
||||
new TNotification<Class, Arg>(aInstance, aMethod, aArg);
|
||||
if (notification && mNotifications.AppendElement(notification)) {
|
||||
if (notification) {
|
||||
// XXX(Bug 1631371) Check if this should use a fallible operation as it
|
||||
// pretended earlier.
|
||||
mNotifications.AppendElement(notification);
|
||||
ScheduleProcessing();
|
||||
}
|
||||
}
|
||||
|
@ -492,7 +492,7 @@ ROLE(SPINBUTTON,
|
||||
NSAccessibilityIncrementorRole, //Subroles: Increment/Decrement.
|
||||
ROLE_SYSTEM_SPINBUTTON,
|
||||
ROLE_SYSTEM_SPINBUTTON,
|
||||
java::SessionAccessibility::CLASSNAME_VIEW, // A composite widget
|
||||
java::SessionAccessibility::CLASSNAME_EDITTEXT,
|
||||
eNameFromValueRule)
|
||||
|
||||
ROLE(DIAGRAM,
|
||||
|
@ -19,15 +19,12 @@ StyleInfo::StyleInfo(dom::Element* aElement) : mElement(aElement) {
|
||||
|
||||
void StyleInfo::Display(nsAString& aValue) {
|
||||
aValue.Truncate();
|
||||
Servo_GetPropertyValue(mComputedStyle, eCSSProperty_display, &aValue);
|
||||
mComputedStyle->GetComputedPropertyValue(eCSSProperty_display, aValue);
|
||||
}
|
||||
|
||||
void StyleInfo::TextAlign(nsAString& aValue) {
|
||||
aValue.Truncate();
|
||||
AppendASCIItoUTF16(
|
||||
nsCSSProps::ValueToKeyword(mComputedStyle->StyleText()->mTextAlign,
|
||||
nsCSSProps::kTextAlignKTable),
|
||||
aValue);
|
||||
mComputedStyle->GetComputedPropertyValue(eCSSProperty_text_align, aValue);
|
||||
}
|
||||
|
||||
void StyleInfo::TextIndent(nsAString& aValue) {
|
||||
@ -72,7 +69,23 @@ void StyleInfo::FormatColor(const nscolor& aValue, nsString& aFormattedValue) {
|
||||
|
||||
void StyleInfo::FormatTextDecorationStyle(uint8_t aValue,
|
||||
nsAString& aFormattedValue) {
|
||||
nsCSSKeyword keyword = nsCSSProps::ValueToKeywordEnum(
|
||||
aValue, nsCSSProps::kTextDecorationStyleKTable);
|
||||
AppendUTF8toUTF16(nsCSSKeywords::GetStringValue(keyword), aFormattedValue);
|
||||
// TODO: When these are enum classes that rust also understands we should just
|
||||
// make an FFI call here.
|
||||
switch (aValue) {
|
||||
case NS_STYLE_TEXT_DECORATION_STYLE_NONE:
|
||||
return aFormattedValue.AssignASCII("-moz-none");
|
||||
case NS_STYLE_TEXT_DECORATION_STYLE_SOLID:
|
||||
return aFormattedValue.AssignASCII("solid");
|
||||
case NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE:
|
||||
return aFormattedValue.AssignASCII("double");
|
||||
case NS_STYLE_TEXT_DECORATION_STYLE_DOTTED:
|
||||
return aFormattedValue.AssignASCII("dotted");
|
||||
case NS_STYLE_TEXT_DECORATION_STYLE_DASHED:
|
||||
return aFormattedValue.AssignASCII("dashed");
|
||||
case NS_STYLE_TEXT_DECORATION_STYLE_WAVY:
|
||||
return aFormattedValue.AssignASCII("wavy");
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unknown decoration style");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "nsIPersistentProperties2.h"
|
||||
#include "mozilla/a11y/PDocAccessibleChild.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsAccessibilityService.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
@ -137,7 +138,11 @@ void nsAccUtils::SetLiveContainerAttributes(
|
||||
live);
|
||||
} else if (role) {
|
||||
GetLiveAttrValue(role->liveAttRule, live);
|
||||
} else if (nsStaticAtom* value = GetAccService()->MarkupAttribute(
|
||||
ancestor, nsGkAtoms::live)) {
|
||||
value->ToString(live);
|
||||
}
|
||||
|
||||
if (!live.IsEmpty()) {
|
||||
SetAccAttr(aAttributes, nsGkAtoms::containerLive, live);
|
||||
if (role) {
|
||||
@ -487,6 +492,9 @@ bool nsAccUtils::IsARIALive(const Accessible* aAccessible) {
|
||||
docLive);
|
||||
} else if (role) {
|
||||
GetLiveAttrValue(role->liveAttRule, docLive);
|
||||
} else if (nsStaticAtom* value = GetAccService()->MarkupAttribute(
|
||||
ancestor, nsGkAtoms::live)) {
|
||||
value->ToString(docLive);
|
||||
}
|
||||
if (!docLive.IsEmpty()) {
|
||||
live = docLive;
|
||||
|
@ -335,6 +335,25 @@ void nsAccessibilityService::FireAccessibleEvent(uint32_t aEvent,
|
||||
nsEventShell::FireEvent(aEvent, aTarget);
|
||||
}
|
||||
|
||||
void nsAccessibilityService::NotifyOfImageSizeAvailable(
|
||||
mozilla::PresShell* aPresShell, nsIContent* aContent) {
|
||||
// If the size of an image is initially unknown, it will have the invisible
|
||||
// state (and a 0 width and height), causing it to be ignored by some screen
|
||||
// readers. Fire a state change event to update any client caches.
|
||||
DocAccessible* document = GetDocAccessible(aPresShell);
|
||||
if (document) {
|
||||
Accessible* accessible = document->GetAccessible(aContent);
|
||||
// The accessible may not be an ImageAccessible if this was previously a
|
||||
// broken image with an alt attribute. In that case, do nothing; the
|
||||
// accessible will be recreated if this becomes a valid image.
|
||||
if (accessible && accessible->IsImage()) {
|
||||
RefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(accessible, states::INVISIBLE, false);
|
||||
document->FireDelayedEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Accessible* nsAccessibilityService::GetRootDocumentAccessible(
|
||||
PresShell* aPresShell, bool aCanCreate) {
|
||||
PresShell* presShell = aPresShell;
|
||||
@ -343,7 +362,7 @@ Accessible* nsAccessibilityService::GetRootDocumentAccessible(
|
||||
nsCOMPtr<nsIDocShellTreeItem> treeItem(documentNode->GetDocShell());
|
||||
if (treeItem) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
|
||||
treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
|
||||
treeItem->GetInProcessRootTreeItem(getter_AddRefs(rootTreeItem));
|
||||
if (treeItem != rootTreeItem) {
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(rootTreeItem));
|
||||
presShell = docShell->GetPresShell();
|
||||
|
@ -222,6 +222,15 @@ class nsAccessibilityService final : public mozilla::a11y::DocManager,
|
||||
|
||||
void FireAccessibleEvent(uint32_t aEvent, Accessible* aTarget);
|
||||
|
||||
/**
|
||||
* Notify accessibility that the size has become available for an image.
|
||||
* This occurs when the size of an image is initially not known, but we've
|
||||
* now loaded enough data to know the size.
|
||||
* Called by layout.
|
||||
*/
|
||||
void NotifyOfImageSizeAvailable(mozilla::PresShell* aPresShell,
|
||||
nsIContent* aContent);
|
||||
|
||||
// nsAccessibiltiyService
|
||||
|
||||
/**
|
||||
@ -246,6 +255,25 @@ class nsAccessibilityService final : public mozilla::a11y::DocManager,
|
||||
return markupMap ? markupMap->role : mozilla::a11y::roles::NOTHING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the associated value for a given attribute if
|
||||
* it appears in the MarkupMap. Otherwise, it returns null.
|
||||
*/
|
||||
nsStaticAtom* MarkupAttribute(const nsIContent* aContent,
|
||||
nsStaticAtom* aAtom) const {
|
||||
const mozilla::a11y::HTMLMarkupMapInfo* markupMap =
|
||||
mHTMLMarkupMap.Get(aContent->NodeInfo()->NameAtom());
|
||||
if (markupMap) {
|
||||
for (size_t i = 0; i < mozilla::ArrayLength(markupMap->attrs); i++) {
|
||||
const mozilla::a11y::MarkupAttrInfo* info = markupMap->attrs + i;
|
||||
if (info->name == aAtom) {
|
||||
return info->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the object attribute defined by markup for the given element.
|
||||
*/
|
||||
|
@ -364,7 +364,7 @@ bool nsCoreUtils::IsTabDocument(Document* aDocumentNode) {
|
||||
|
||||
// Parent of docshell for tab document running in chrome process is root.
|
||||
nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
|
||||
treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
|
||||
treeItem->GetInProcessRootTreeItem(getter_AddRefs(rootTreeItem));
|
||||
|
||||
return parentTreeItem == rootTreeItem;
|
||||
}
|
||||
|
@ -142,8 +142,8 @@ class nsCoreUtils {
|
||||
* @param aRange the range to scroll to
|
||||
* @param aScrollType the place a range should be scrolled to
|
||||
*/
|
||||
static nsresult ScrollSubstringTo(nsIFrame* aFrame, nsRange* aRange,
|
||||
uint32_t aScrollType);
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY static nsresult ScrollSubstringTo(
|
||||
nsIFrame* aFrame, nsRange* aRange, uint32_t aScrollType);
|
||||
|
||||
/** Helper method to scroll range into view, used for implementation of
|
||||
* nsIAccessibleText::scrollSubstringTo[Point]().
|
||||
@ -155,9 +155,9 @@ class nsCoreUtils {
|
||||
* @param aHorizontal how to align horizontally, specified in percents,
|
||||
* and when.
|
||||
*/
|
||||
static nsresult ScrollSubstringTo(nsIFrame* aFrame, nsRange* aRange,
|
||||
mozilla::ScrollAxis aVertical,
|
||||
mozilla::ScrollAxis aHorizontal);
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY static nsresult ScrollSubstringTo(
|
||||
nsIFrame* aFrame, nsRange* aRange, mozilla::ScrollAxis aVertical,
|
||||
mozilla::ScrollAxis aHorizontal);
|
||||
|
||||
/**
|
||||
* Scrolls the given frame to the point, used for implememntation of
|
||||
|
@ -65,7 +65,6 @@
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/BasicEvents.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/EventStateManager.h"
|
||||
#include "mozilla/EventStates.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/MouseEvents.h"
|
||||
@ -79,6 +78,7 @@
|
||||
#include "mozilla/dom/HTMLBodyElement.h"
|
||||
#include "mozilla/dom/KeyboardEventBinding.h"
|
||||
#include "mozilla/dom/TreeWalker.h"
|
||||
#include "mozilla/dom/UserActivation.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
@ -736,7 +736,7 @@ void Accessible::TakeFocus() const {
|
||||
|
||||
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
if (fm) {
|
||||
AutoHandlingUserInputStatePusher inputStatePusher(true);
|
||||
dom::AutoHandlingUserInputStatePusher inputStatePusher(true);
|
||||
// XXXbz: Can we actually have a non-element content here?
|
||||
RefPtr<Element> element =
|
||||
focusContent->IsElement() ? focusContent->AsElement() : nullptr;
|
||||
@ -2074,7 +2074,7 @@ RootAccessible* Accessible::RootAccessible() const {
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> root;
|
||||
docShell->GetRootTreeItem(getter_AddRefs(root));
|
||||
docShell->GetInProcessRootTreeItem(getter_AddRefs(root));
|
||||
NS_ASSERTION(root, "No root content tree item");
|
||||
if (!root) {
|
||||
return nullptr;
|
||||
@ -2106,10 +2106,13 @@ bool Accessible::InsertChildAt(uint32_t aIndex, Accessible* aChild) {
|
||||
if (!aChild) return false;
|
||||
|
||||
if (aIndex == mChildren.Length()) {
|
||||
if (!mChildren.AppendElement(aChild)) return false;
|
||||
|
||||
// XXX(Bug 1631371) Check if this should use a fallible operation as it
|
||||
// pretended earlier.
|
||||
mChildren.AppendElement(aChild);
|
||||
} else {
|
||||
if (!mChildren.InsertElementAt(aIndex, aChild)) return false;
|
||||
// XXX(Bug 1631371) Check if this should use a fallible operation as it
|
||||
// pretended earlier.
|
||||
mChildren.InsertElementAt(aIndex, aChild);
|
||||
|
||||
MOZ_ASSERT(mStateFlags & eKidsMutating, "Illicit children change");
|
||||
|
||||
|
@ -110,8 +110,10 @@ inline void DocAccessible::NotifyOfLoad(uint32_t aLoadEventType) {
|
||||
}
|
||||
|
||||
inline void DocAccessible::MaybeNotifyOfValueChange(Accessible* aAccessible) {
|
||||
if (aAccessible->IsCombobox() || aAccessible->Role() == roles::ENTRY)
|
||||
if (aAccessible->IsCombobox() || aAccessible->Role() == roles::ENTRY ||
|
||||
aAccessible->Role() == roles::SPINBUTTON) {
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE, aAccessible);
|
||||
}
|
||||
}
|
||||
|
||||
inline Accessible* DocAccessible::GetAccessibleEvenIfNotInMapOrContainer(
|
||||
|
@ -35,15 +35,16 @@
|
||||
#include "nsFocusManager.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/EventStateManager.h"
|
||||
#include "mozilla/EventStates.h"
|
||||
#include "mozilla/HTMLEditor.h"
|
||||
#include "mozilla/PresShell.h"
|
||||
#include "mozilla/TextEditor.h"
|
||||
#include "mozilla/dom/AncestorIterator.h"
|
||||
#include "mozilla/dom/BrowserChild.h"
|
||||
#include "mozilla/dom/DocumentType.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/MutationEventBinding.h"
|
||||
#include "mozilla/dom/UserActivation.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
@ -290,7 +291,7 @@ void DocAccessible::TakeFocus() const {
|
||||
// Focus the document.
|
||||
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
RefPtr<dom::Element> newFocus;
|
||||
AutoHandlingUserInputStatePusher inputStatePusher(true);
|
||||
dom::AutoHandlingUserInputStatePusher inputStatePusher(true);
|
||||
fm->MoveFocus(mDocumentNode->GetWindow(), nullptr,
|
||||
nsFocusManager::MOVEFOCUS_ROOT, 0, getter_AddRefs(newFocus));
|
||||
}
|
||||
@ -1136,24 +1137,20 @@ Accessible* DocAccessible::GetAccessibleOrContainer(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsINode* currNode = nullptr;
|
||||
if (aNode->IsShadowRoot()) {
|
||||
nsINode* start = aNode;
|
||||
if (auto* shadowRoot = dom::ShadowRoot::FromNode(aNode)) {
|
||||
// This can happen, for example, when called within
|
||||
// SelectionManager::ProcessSelectionChanged due to focusing a direct
|
||||
// child of a shadow root.
|
||||
// GetFlattenedTreeParent works on children of a shadow root, but not the
|
||||
// shadow root itself.
|
||||
const dom::ShadowRoot* shadowRoot = dom::ShadowRoot::FromNode(aNode);
|
||||
currNode = shadowRoot->GetHost();
|
||||
if (!currNode) {
|
||||
start = shadowRoot->GetHost();
|
||||
if (!start) {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
currNode = aNode;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(currNode);
|
||||
for (; currNode; currNode = currNode->GetFlattenedTreeParentNode()) {
|
||||
for (nsINode* currNode : dom::InclusiveFlatTreeAncestors(*start)) {
|
||||
// No container if is inside of aria-hidden subtree.
|
||||
if (aNoContainerIfPruned && currNode->IsElement() &&
|
||||
aria::HasDefinedARIAHidden(currNode->AsElement())) {
|
||||
@ -1218,7 +1215,7 @@ void DocAccessible::BindToDocument(Accessible* aAccessible,
|
||||
mNodeToAccessibleMap.Put(aAccessible->GetNode(), aAccessible);
|
||||
|
||||
// Put into unique ID cache.
|
||||
mAccessibleCache.Put(aAccessible->UniqueID(), aAccessible);
|
||||
mAccessibleCache.Put(aAccessible->UniqueID(), RefPtr{aAccessible});
|
||||
|
||||
aAccessible->SetRoleMapEntry(aRoleMapEntry);
|
||||
|
||||
@ -1639,7 +1636,7 @@ class InsertIterator final {
|
||||
MOZ_ASSERT(aNodes, "No nodes to search for accessible elements");
|
||||
MOZ_COUNT_CTOR(InsertIterator);
|
||||
}
|
||||
~InsertIterator() { MOZ_COUNT_DTOR(InsertIterator); }
|
||||
MOZ_COUNTED_DTOR(InsertIterator)
|
||||
|
||||
Accessible* Context() const { return mWalker.Context(); }
|
||||
Accessible* Child() const { return mChild; }
|
||||
@ -2287,7 +2284,7 @@ bool DocAccessible::IsLoadEventTarget() const {
|
||||
// Return true if it's either:
|
||||
// a) tab document;
|
||||
nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
|
||||
treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
|
||||
treeItem->GetInProcessRootTreeItem(getter_AddRefs(rootTreeItem));
|
||||
if (parentTreeItem == rootTreeItem) return true;
|
||||
|
||||
// b) frame/iframe document and its parent document is not in loading state
|
||||
|
@ -432,7 +432,10 @@ class DocAccessible : public HyperTextAccessibleWrap,
|
||||
* accessibles.
|
||||
*/
|
||||
bool AppendChildDocument(DocAccessible* aChildDocument) {
|
||||
return mChildDocuments.AppendElement(aChildDocument);
|
||||
// XXX(Bug 1631371) Check if this should use a fallible operation as it
|
||||
// pretended earlier, or change the return type to void.
|
||||
mChildDocuments.AppendElement(aChildDocument);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -68,7 +68,7 @@ role HyperTextAccessible::NativeRole() const {
|
||||
uint64_t HyperTextAccessible::NativeState() const {
|
||||
uint64_t states = AccessibleWrap::NativeState();
|
||||
|
||||
if (mContent->AsElement()->State().HasState(NS_EVENT_STATE_MOZ_READWRITE)) {
|
||||
if (mContent->AsElement()->State().HasState(NS_EVENT_STATE_READWRITE)) {
|
||||
states |= states::EDITABLE;
|
||||
|
||||
} else if (mContent->IsHTMLElement(nsGkAtoms::article)) {
|
||||
@ -324,7 +324,7 @@ static nsIContent* GetElementAsContentOf(nsINode* aNode) {
|
||||
|
||||
bool HyperTextAccessible::OffsetsToDOMRange(int32_t aStartOffset,
|
||||
int32_t aEndOffset,
|
||||
nsRange* aRange) {
|
||||
nsRange* aRange) const {
|
||||
DOMPoint startPoint = OffsetToDOMPoint(aStartOffset);
|
||||
if (!startPoint.node) return false;
|
||||
|
||||
@ -357,7 +357,7 @@ bool HyperTextAccessible::OffsetsToDOMRange(int32_t aStartOffset,
|
||||
return true;
|
||||
}
|
||||
|
||||
DOMPoint HyperTextAccessible::OffsetToDOMPoint(int32_t aOffset) {
|
||||
DOMPoint HyperTextAccessible::OffsetToDOMPoint(int32_t aOffset) const {
|
||||
// 0 offset is valid even if no children. In this case the associated editor
|
||||
// is empty so return a DOM point for editor root element.
|
||||
if (aOffset == 0) {
|
||||
@ -404,7 +404,7 @@ DOMPoint HyperTextAccessible::OffsetToDOMPoint(int32_t aOffset) {
|
||||
}
|
||||
|
||||
DOMPoint HyperTextAccessible::ClosestNotGeneratedDOMPoint(
|
||||
const DOMPoint& aDOMPoint, nsIContent* aElementContent) {
|
||||
const DOMPoint& aDOMPoint, nsIContent* aElementContent) const {
|
||||
MOZ_ASSERT(aDOMPoint.node, "The node must not be null");
|
||||
|
||||
// ::before pseudo element
|
||||
@ -521,8 +521,10 @@ uint32_t HyperTextAccessible::FindOffset(uint32_t aOffset,
|
||||
nsresult rv = frameAtOffset->PeekOffset(&pos);
|
||||
|
||||
// PeekOffset fails on last/first lines of the text in certain cases.
|
||||
bool fallBackToSelectEndLine = false;
|
||||
if (NS_FAILED(rv) && aAmount == eSelectLine) {
|
||||
pos.mAmount = (aDirection == eDirNext) ? eSelectEndLine : eSelectBeginLine;
|
||||
fallBackToSelectEndLine = aDirection == eDirNext;
|
||||
pos.mAmount = fallBackToSelectEndLine ? eSelectEndLine : eSelectBeginLine;
|
||||
frameAtOffset->PeekOffset(&pos);
|
||||
}
|
||||
if (!pos.mResultContent) {
|
||||
@ -534,6 +536,14 @@ uint32_t HyperTextAccessible::FindOffset(uint32_t aOffset,
|
||||
uint32_t hyperTextOffset = DOMPointToOffset(
|
||||
pos.mResultContent, pos.mContentOffset, aDirection == eDirNext);
|
||||
|
||||
if (fallBackToSelectEndLine && IsLineEndCharAt(hyperTextOffset)) {
|
||||
// We used eSelectEndLine, but the caller requested eSelectLine.
|
||||
// If there's a '\n' at the end of the line, eSelectEndLine will stop
|
||||
// on it rather than after it. This is not what we want, since the caller
|
||||
// wants the next line, not the same line.
|
||||
++hyperTextOffset;
|
||||
}
|
||||
|
||||
if (aDirection == eDirPrevious) {
|
||||
// If we reached the end during search, this means we didn't find the DOM
|
||||
// point and we're actually at the start of the paragraph
|
||||
@ -1260,13 +1270,15 @@ nsresult HyperTextAccessible::SetSelectionRange(int32_t aStartPos,
|
||||
// some input controls
|
||||
if (isFocusable) TakeFocus();
|
||||
|
||||
dom::Selection* domSel = DOMSelection();
|
||||
RefPtr<dom::Selection> domSel = DOMSelection();
|
||||
NS_ENSURE_STATE(domSel);
|
||||
|
||||
// Set up the selection.
|
||||
for (int32_t idx = domSel->RangeCount() - 1; idx > 0; idx--)
|
||||
domSel->RemoveRangeAndUnselectFramesAndNotifyListeners(
|
||||
*domSel->GetRangeAt(idx), IgnoreErrors());
|
||||
for (int32_t idx = domSel->RangeCount() - 1; idx > 0; idx--) {
|
||||
RefPtr<nsRange> range{domSel->GetRangeAt(idx)};
|
||||
domSel->RemoveRangeAndUnselectFramesAndNotifyListeners(*range,
|
||||
IgnoreErrors());
|
||||
}
|
||||
SetSelectionBoundsAt(0, aStartPos, aEndPos);
|
||||
|
||||
// Make sure it is visible
|
||||
@ -1552,15 +1564,16 @@ bool HyperTextAccessible::SetSelectionBoundsAt(int32_t aSelectionNum,
|
||||
return false;
|
||||
}
|
||||
|
||||
dom::Selection* domSel = DOMSelection();
|
||||
RefPtr<dom::Selection> domSel = DOMSelection();
|
||||
if (!domSel) return false;
|
||||
|
||||
RefPtr<nsRange> range;
|
||||
uint32_t rangeCount = domSel->RangeCount();
|
||||
if (aSelectionNum == static_cast<int32_t>(rangeCount))
|
||||
range = new nsRange(mContent);
|
||||
else
|
||||
if (aSelectionNum == static_cast<int32_t>(rangeCount)) {
|
||||
range = nsRange::Create(mContent);
|
||||
} else {
|
||||
range = domSel->GetRangeAt(aSelectionNum);
|
||||
}
|
||||
|
||||
if (!range) return false;
|
||||
|
||||
@ -1589,22 +1602,23 @@ bool HyperTextAccessible::SetSelectionBoundsAt(int32_t aSelectionNum,
|
||||
}
|
||||
|
||||
bool HyperTextAccessible::RemoveFromSelection(int32_t aSelectionNum) {
|
||||
dom::Selection* domSel = DOMSelection();
|
||||
RefPtr<dom::Selection> domSel = DOMSelection();
|
||||
if (!domSel) return false;
|
||||
|
||||
if (aSelectionNum < 0 ||
|
||||
aSelectionNum >= static_cast<int32_t>(domSel->RangeCount()))
|
||||
return false;
|
||||
|
||||
domSel->RemoveRangeAndUnselectFramesAndNotifyListeners(
|
||||
*domSel->GetRangeAt(aSelectionNum), IgnoreErrors());
|
||||
const RefPtr<nsRange> range{domSel->GetRangeAt(aSelectionNum)};
|
||||
domSel->RemoveRangeAndUnselectFramesAndNotifyListeners(*range,
|
||||
IgnoreErrors());
|
||||
return true;
|
||||
}
|
||||
|
||||
void HyperTextAccessible::ScrollSubstringTo(int32_t aStartOffset,
|
||||
int32_t aEndOffset,
|
||||
uint32_t aScrollType) {
|
||||
RefPtr<nsRange> range = new nsRange(mContent);
|
||||
RefPtr<nsRange> range = nsRange::Create(mContent);
|
||||
if (OffsetsToDOMRange(aStartOffset, aEndOffset, range))
|
||||
nsCoreUtils::ScrollSubstringTo(GetFrame(), range, aScrollType);
|
||||
}
|
||||
@ -1619,7 +1633,7 @@ void HyperTextAccessible::ScrollSubstringToPoint(int32_t aStartOffset,
|
||||
nsIntPoint coords =
|
||||
nsAccUtils::ConvertToScreenCoords(aX, aY, aCoordinateType, this);
|
||||
|
||||
RefPtr<nsRange> range = new nsRange(mContent);
|
||||
RefPtr<nsRange> range = nsRange::Create(mContent);
|
||||
if (!OffsetsToDOMRange(aStartOffset, aEndOffset, range)) return;
|
||||
|
||||
nsPresContext* presContext = frame->PresContext();
|
||||
@ -1683,7 +1697,7 @@ void HyperTextAccessible::SelectionRanges(
|
||||
aRanges->SetCapacity(sel->RangeCount());
|
||||
|
||||
for (uint32_t idx = 0; idx < sel->RangeCount(); idx++) {
|
||||
nsRange* DOMRange = sel->GetRangeAt(idx);
|
||||
const nsRange* DOMRange = sel->GetRangeAt(idx);
|
||||
HyperTextAccessible* startContainer =
|
||||
nsAccUtils::GetTextContainer(DOMRange->GetStartContainer());
|
||||
HyperTextAccessible* endContainer =
|
||||
@ -2003,7 +2017,7 @@ void HyperTextAccessible::GetSpellTextAttr(
|
||||
|
||||
uint32_t startOffset = 0, endOffset = 0;
|
||||
for (int32_t idx = 0; idx < rangeCount; idx++) {
|
||||
nsRange* range = domSel->GetRangeAt(idx);
|
||||
const nsRange* range = domSel->GetRangeAt(idx);
|
||||
if (range->Collapsed()) continue;
|
||||
|
||||
// See if the point comes after the range in which case we must continue in
|
||||
@ -2057,7 +2071,7 @@ void HyperTextAccessible::GetSpellTextAttr(
|
||||
endOffset = DOMPointToOffset(startNode, startNodeOffset);
|
||||
|
||||
if (idx > 0) {
|
||||
nsRange* prevRange = domSel->GetRangeAt(idx - 1);
|
||||
const nsRange* prevRange = domSel->GetRangeAt(idx - 1);
|
||||
startOffset = DOMPointToOffset(prevRange->GetEndContainer(),
|
||||
prevRange->EndOffset());
|
||||
}
|
||||
@ -2077,7 +2091,7 @@ void HyperTextAccessible::GetSpellTextAttr(
|
||||
// the point is not in a range, that we do not need to compute an end offset,
|
||||
// and that we should use the end offset of the last range to compute the
|
||||
// start offset of the text attribute range.
|
||||
nsRange* prevRange = domSel->GetRangeAt(rangeCount - 1);
|
||||
const nsRange* prevRange = domSel->GetRangeAt(rangeCount - 1);
|
||||
startOffset =
|
||||
DOMPointToOffset(prevRange->GetEndContainer(), prevRange->EndOffset());
|
||||
|
||||
|
@ -142,7 +142,7 @@ class HyperTextAccessible : public AccessibleWrap {
|
||||
* @return true if conversion was successful
|
||||
*/
|
||||
bool OffsetsToDOMRange(int32_t aStartOffset, int32_t aEndOffset,
|
||||
nsRange* aRange);
|
||||
nsRange* aRange) const;
|
||||
|
||||
/**
|
||||
* Convert the given offset into DOM point.
|
||||
@ -151,7 +151,7 @@ class HyperTextAccessible : public AccessibleWrap {
|
||||
* if before embedded object then (parent node, indexInParent), if after then
|
||||
* (parent node, indexInParent + 1).
|
||||
*/
|
||||
DOMPoint OffsetToDOMPoint(int32_t aOffset);
|
||||
DOMPoint OffsetToDOMPoint(int32_t aOffset) const;
|
||||
|
||||
/**
|
||||
* Return true if the used ARIA role (if any) allows the hypertext accessible
|
||||
@ -340,8 +340,10 @@ class HyperTextAccessible : public AccessibleWrap {
|
||||
* Changes the start and end offset of the specified selection.
|
||||
* @return true if succeeded
|
||||
*/
|
||||
bool SetSelectionBoundsAt(int32_t aSelectionNum, int32_t aStartOffset,
|
||||
int32_t aEndOffset);
|
||||
// TODO: annotate this with `MOZ_CAN_RUN_SCRIPT` instead.
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY bool SetSelectionBoundsAt(int32_t aSelectionNum,
|
||||
int32_t aStartOffset,
|
||||
int32_t aEndOffset);
|
||||
|
||||
/**
|
||||
* Adds a selection bounded by the specified offsets.
|
||||
@ -353,7 +355,8 @@ class HyperTextAccessible : public AccessibleWrap {
|
||||
* Removes the specified selection.
|
||||
* @return true if succeeded
|
||||
*/
|
||||
bool RemoveFromSelection(int32_t aSelectionNum);
|
||||
// TODO: annotate this with `MOZ_CAN_RUN_SCRIPT` instead.
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY bool RemoveFromSelection(int32_t aSelectionNum);
|
||||
|
||||
/**
|
||||
* Scroll the given text range into view.
|
||||
@ -507,7 +510,9 @@ class HyperTextAccessible : public AccessibleWrap {
|
||||
void GetSelectionDOMRanges(SelectionType aSelectionType,
|
||||
nsTArray<nsRange*>* aRanges);
|
||||
|
||||
nsresult SetSelectionRange(int32_t aStartPos, int32_t aEndPos);
|
||||
// TODO: annotate this with `MOZ_CAN_RUN_SCRIPT` instead.
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult SetSelectionRange(int32_t aStartPos,
|
||||
int32_t aEndPos);
|
||||
|
||||
/**
|
||||
* Convert the given DOM point to a DOM point in non-generated contents.
|
||||
@ -524,7 +529,7 @@ class HyperTextAccessible : public AccessibleWrap {
|
||||
* contents.
|
||||
*/
|
||||
DOMPoint ClosestNotGeneratedDOMPoint(const DOMPoint& aDOMPoint,
|
||||
nsIContent* aElementContent);
|
||||
nsIContent* aElementContent) const;
|
||||
|
||||
// Helpers
|
||||
nsresult GetDOMPointByFrameOffset(nsIFrame* aFrame, int32_t aOffset,
|
||||
|
@ -47,13 +47,30 @@ uint64_t ImageAccessible::NativeState() const {
|
||||
content->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
|
||||
getter_AddRefs(imageRequest));
|
||||
|
||||
nsCOMPtr<imgIContainer> imgContainer;
|
||||
if (imageRequest) imageRequest->GetImage(getter_AddRefs(imgContainer));
|
||||
if (imageRequest) {
|
||||
nsCOMPtr<imgIContainer> imgContainer;
|
||||
imageRequest->GetImage(getter_AddRefs(imgContainer));
|
||||
if (imgContainer) {
|
||||
bool animated = false;
|
||||
imgContainer->GetAnimated(&animated);
|
||||
if (animated) {
|
||||
state |= states::ANIMATED;
|
||||
}
|
||||
}
|
||||
|
||||
if (imgContainer) {
|
||||
bool animated = false;
|
||||
imgContainer->GetAnimated(&animated);
|
||||
if (animated) state |= states::ANIMATED;
|
||||
nsIFrame* frame = GetFrame();
|
||||
MOZ_ASSERT(!frame || frame->AccessibleType() == eImageType ||
|
||||
frame->AccessibleType() == a11y::eHTMLImageMapType);
|
||||
if (frame && !(frame->GetStateBits() & IMAGE_SIZECONSTRAINED)) {
|
||||
uint32_t status = imgIRequest::STATUS_NONE;
|
||||
imageRequest->GetImageStatus(&status);
|
||||
if (!(status & imgIRequest::STATUS_SIZE_AVAILABLE)) {
|
||||
// The size of this image hasn't been constrained and we haven't loaded
|
||||
// enough of the image to know its size yet. This means it currently
|
||||
// has 0 width and height.
|
||||
state |= states::INVISIBLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
|
@ -459,7 +459,7 @@ Accessible* HTMLFileInputAccessible::CurrentItem() const {
|
||||
role HTMLSpinnerAccessible::NativeRole() const { return roles::SPINBUTTON; }
|
||||
|
||||
void HTMLSpinnerAccessible::Value(nsString& aValue) const {
|
||||
AccessibleWrap::Value(aValue);
|
||||
HTMLTextFieldAccessible::Value(aValue);
|
||||
if (!aValue.IsEmpty()) return;
|
||||
|
||||
// Pass NonSystem as the caller type, to be safe. We don't expect to have a
|
||||
@ -468,28 +468,28 @@ void HTMLSpinnerAccessible::Value(nsString& aValue) const {
|
||||
}
|
||||
|
||||
double HTMLSpinnerAccessible::MaxValue() const {
|
||||
double value = AccessibleWrap::MaxValue();
|
||||
double value = HTMLTextFieldAccessible::MaxValue();
|
||||
if (!IsNaN(value)) return value;
|
||||
|
||||
return HTMLInputElement::FromNode(mContent)->GetMaximum().toDouble();
|
||||
}
|
||||
|
||||
double HTMLSpinnerAccessible::MinValue() const {
|
||||
double value = AccessibleWrap::MinValue();
|
||||
double value = HTMLTextFieldAccessible::MinValue();
|
||||
if (!IsNaN(value)) return value;
|
||||
|
||||
return HTMLInputElement::FromNode(mContent)->GetMinimum().toDouble();
|
||||
}
|
||||
|
||||
double HTMLSpinnerAccessible::Step() const {
|
||||
double value = AccessibleWrap::Step();
|
||||
double value = HTMLTextFieldAccessible::Step();
|
||||
if (!IsNaN(value)) return value;
|
||||
|
||||
return HTMLInputElement::FromNode(mContent)->GetStep().toDouble();
|
||||
}
|
||||
|
||||
double HTMLSpinnerAccessible::CurValue() const {
|
||||
double value = AccessibleWrap::CurValue();
|
||||
double value = HTMLTextFieldAccessible::CurValue();
|
||||
if (!IsNaN(value)) return value;
|
||||
|
||||
return HTMLInputElement::FromNode(mContent)->GetValueAsDecimal().toDouble();
|
||||
|
@ -62,7 +62,7 @@ class HTMLButtonAccessible : public HyperTextAccessibleWrap {
|
||||
* Accessible for HTML input@type="text", input@type="password", textarea and
|
||||
* other HTML text controls.
|
||||
*/
|
||||
class HTMLTextFieldAccessible final : public HyperTextAccessibleWrap {
|
||||
class HTMLTextFieldAccessible : public HyperTextAccessibleWrap {
|
||||
public:
|
||||
enum { eAction_Click = 0 };
|
||||
|
||||
@ -128,10 +128,10 @@ class HTMLFileInputAccessible : public HyperTextAccessibleWrap {
|
||||
/**
|
||||
* Used for HTML input@type="number".
|
||||
*/
|
||||
class HTMLSpinnerAccessible : public AccessibleWrap {
|
||||
class HTMLSpinnerAccessible final : public HTMLTextFieldAccessible {
|
||||
public:
|
||||
HTMLSpinnerAccessible(nsIContent* aContent, DocAccessible* aDoc)
|
||||
: AccessibleWrap(aContent, aDoc) {
|
||||
: HTMLTextFieldAccessible(aContent, aDoc) {
|
||||
mStateFlags |= eHasNumericValue;
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "Role.h"
|
||||
#include "States.h"
|
||||
|
||||
#include "nsContainerFrame.h"
|
||||
#include "nsBulletFrame.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
@ -36,10 +36,14 @@ HTMLLIAccessible::HTMLLIAccessible(nsIContent* aContent, DocAccessible* aDoc)
|
||||
: HyperTextAccessibleWrap(aContent, aDoc), mBullet(nullptr) {
|
||||
mType = eHTMLLiType;
|
||||
|
||||
if (nsLayoutUtils::GetMarkerFrame(aContent)) {
|
||||
mBullet = new HTMLListBulletAccessible(mContent, mDoc);
|
||||
Document()->BindToDocument(mBullet, nullptr);
|
||||
AppendChild(mBullet);
|
||||
if (nsBulletFrame* bulletFrame =
|
||||
do_QueryFrame(nsLayoutUtils::GetMarkerFrame(aContent))) {
|
||||
const nsStyleList* styleList = bulletFrame->StyleList();
|
||||
if (styleList->GetListStyleImage() || !styleList->mCounterStyle.IsNone()) {
|
||||
mBullet = new HTMLListBulletAccessible(mContent, mDoc);
|
||||
Document()->BindToDocument(mBullet, nullptr);
|
||||
AppendChild(mBullet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,10 +127,20 @@ ENameValueFlag HTMLListBulletAccessible::Name(nsString& aName) const {
|
||||
aName.Truncate();
|
||||
|
||||
// Native anonymous content, ARIA can't be used. Get list bullet text.
|
||||
if (nsContainerFrame* frame = do_QueryFrame(mContent->GetPrimaryFrame())) {
|
||||
frame->GetSpokenMarkerText(aName);
|
||||
nsBulletFrame* frame = do_QueryFrame(GetFrame());
|
||||
if (!frame) {
|
||||
return eNameOK;
|
||||
}
|
||||
|
||||
if (frame->StyleList()->GetListStyleImage()) {
|
||||
// Bullet is an image, so use default bullet character.
|
||||
const char16_t kDiscCharacter = 0x2022;
|
||||
aName.Assign(kDiscCharacter);
|
||||
aName.Append(' ');
|
||||
return eNameOK;
|
||||
}
|
||||
|
||||
frame->GetSpokenText(aName);
|
||||
return eNameOK;
|
||||
}
|
||||
|
||||
|
@ -658,36 +658,36 @@ bool HTMLTableAccessible::IsCellSelected(uint32_t aRowIdx, uint32_t aColIdx) {
|
||||
|
||||
void HTMLTableAccessible::SelectRow(uint32_t aRowIdx) {
|
||||
DebugOnly<nsresult> rv =
|
||||
RemoveRowsOrColumnsFromSelection(aRowIdx, TableSelection::Row, true);
|
||||
RemoveRowsOrColumnsFromSelection(aRowIdx, TableSelectionMode::Row, true);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"RemoveRowsOrColumnsFromSelection() Shouldn't fail!");
|
||||
|
||||
AddRowOrColumnToSelection(aRowIdx, TableSelection::Row);
|
||||
AddRowOrColumnToSelection(aRowIdx, TableSelectionMode::Row);
|
||||
}
|
||||
|
||||
void HTMLTableAccessible::SelectCol(uint32_t aColIdx) {
|
||||
DebugOnly<nsresult> rv =
|
||||
RemoveRowsOrColumnsFromSelection(aColIdx, TableSelection::Column, true);
|
||||
DebugOnly<nsresult> rv = RemoveRowsOrColumnsFromSelection(
|
||||
aColIdx, TableSelectionMode::Column, true);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"RemoveRowsOrColumnsFromSelection() Shouldn't fail!");
|
||||
|
||||
AddRowOrColumnToSelection(aColIdx, TableSelection::Column);
|
||||
AddRowOrColumnToSelection(aColIdx, TableSelectionMode::Column);
|
||||
}
|
||||
|
||||
void HTMLTableAccessible::UnselectRow(uint32_t aRowIdx) {
|
||||
RemoveRowsOrColumnsFromSelection(aRowIdx, TableSelection::Row, false);
|
||||
RemoveRowsOrColumnsFromSelection(aRowIdx, TableSelectionMode::Row, false);
|
||||
}
|
||||
|
||||
void HTMLTableAccessible::UnselectCol(uint32_t aColIdx) {
|
||||
RemoveRowsOrColumnsFromSelection(aColIdx, TableSelection::Column, false);
|
||||
RemoveRowsOrColumnsFromSelection(aColIdx, TableSelectionMode::Column, false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// HTMLTableAccessible: protected implementation
|
||||
|
||||
nsresult HTMLTableAccessible::AddRowOrColumnToSelection(
|
||||
int32_t aIndex, TableSelection aTarget) {
|
||||
bool doSelectRow = (aTarget == TableSelection::Row);
|
||||
int32_t aIndex, TableSelectionMode aTarget) {
|
||||
bool doSelectRow = (aTarget == TableSelectionMode::Row);
|
||||
|
||||
nsTableWrapperFrame* tableFrame = do_QueryFrame(mContent->GetPrimaryFrame());
|
||||
if (!tableFrame) return NS_OK;
|
||||
@ -716,7 +716,7 @@ nsresult HTMLTableAccessible::AddRowOrColumnToSelection(
|
||||
}
|
||||
|
||||
nsresult HTMLTableAccessible::RemoveRowsOrColumnsFromSelection(
|
||||
int32_t aIndex, TableSelection aTarget, bool aIsOuter) {
|
||||
int32_t aIndex, TableSelectionMode aTarget, bool aIsOuter) {
|
||||
nsTableWrapperFrame* tableFrame = do_QueryFrame(mContent->GetPrimaryFrame());
|
||||
if (!tableFrame) return NS_OK;
|
||||
|
||||
@ -724,7 +724,7 @@ nsresult HTMLTableAccessible::RemoveRowsOrColumnsFromSelection(
|
||||
RefPtr<nsFrameSelection> tableSelection =
|
||||
const_cast<nsFrameSelection*>(presShell->ConstFrameSelection());
|
||||
|
||||
bool doUnselectRow = (aTarget == TableSelection::Row);
|
||||
bool doUnselectRow = (aTarget == TableSelectionMode::Row);
|
||||
uint32_t count = doUnselectRow ? ColCount() : RowCount();
|
||||
|
||||
int32_t startRowIdx = doUnselectRow ? aIndex : 0;
|
||||
|
@ -14,7 +14,7 @@ class nsTableCellFrame;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
enum class TableSelection : uint32_t;
|
||||
enum class TableSelectionMode : uint32_t;
|
||||
|
||||
namespace a11y {
|
||||
|
||||
@ -176,7 +176,8 @@ class HTMLTableAccessible : public HyperTextAccessibleWrap,
|
||||
* @param aTarget [in] indicates what should be selected, either row or
|
||||
* column (see nsFrameSelection)
|
||||
*/
|
||||
nsresult AddRowOrColumnToSelection(int32_t aIndex, TableSelection aTarget);
|
||||
nsresult AddRowOrColumnToSelection(int32_t aIndex,
|
||||
TableSelectionMode aTarget);
|
||||
|
||||
/**
|
||||
* Removes rows or columns at the given index or outside it from selection.
|
||||
@ -188,7 +189,7 @@ class HTMLTableAccessible : public HyperTextAccessibleWrap,
|
||||
* should be unselected only
|
||||
*/
|
||||
nsresult RemoveRowsOrColumnsFromSelection(int32_t aIndex,
|
||||
TableSelection aTarget,
|
||||
TableSelectionMode aTarget,
|
||||
bool aIsOuter);
|
||||
|
||||
#ifdef SHOW_LAYOUT_HEURISTIC
|
||||
|
@ -25,7 +25,7 @@ class ProxyAccessible : public ProxyAccessibleBase<ProxyAccessible> {
|
||||
MOZ_COUNT_CTOR(ProxyAccessible);
|
||||
}
|
||||
|
||||
~ProxyAccessible() { MOZ_COUNT_DTOR(ProxyAccessible); }
|
||||
MOZ_COUNTED_DTOR(ProxyAccessible)
|
||||
|
||||
#include "mozilla/a11y/ProxyAccessibleShared.h"
|
||||
|
||||
|
@ -2,11 +2,10 @@
|
||||
# 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/.
|
||||
|
||||
# With --disable-accessibility, we need to compile PDocAccessible.ipdl, but
|
||||
# not the C++.
|
||||
IPDL_SOURCES += ['PDocAccessible.ipdl']
|
||||
|
||||
if CONFIG['ACCESSIBILITY']:
|
||||
IPDL_SOURCES += ['PDocAccessible.ipdl']
|
||||
|
||||
EXPORTS.mozilla.a11y += [
|
||||
'DocAccessibleChild.h',
|
||||
'ProxyAccessible.h',
|
||||
|
@ -26,7 +26,7 @@ class ProxyAccessible : public ProxyAccessibleBase<ProxyAccessible> {
|
||||
MOZ_COUNT_CTOR(ProxyAccessible);
|
||||
}
|
||||
|
||||
~ProxyAccessible() { MOZ_COUNT_DTOR(ProxyAccessible); }
|
||||
MOZ_COUNTED_DTOR(ProxyAccessible)
|
||||
|
||||
#include "mozilla/a11y/ProxyAccessibleShared.h"
|
||||
|
||||
|
@ -8,15 +8,9 @@ if CONFIG['COMPILE_ENVIRONMENT'] and CONFIG['ACCESSIBILITY']:
|
||||
'typelib',
|
||||
]
|
||||
|
||||
# With --disable-accessibility, we need to compile PDocAccessible.ipdl (which
|
||||
# also depends on COMPtrTypes.h), but not the C++.
|
||||
IPDL_SOURCES += ['PDocAccessible.ipdl']
|
||||
|
||||
EXPORTS.mozilla.a11y += [
|
||||
'COMPtrTypes.h',
|
||||
]
|
||||
|
||||
if CONFIG['ACCESSIBILITY']:
|
||||
IPDL_SOURCES += ['PDocAccessible.ipdl']
|
||||
|
||||
if not CONFIG['HAVE_64BIT_BUILD']:
|
||||
EXPORTS += [
|
||||
'IAccessible32.manifest',
|
||||
@ -27,6 +21,7 @@ if CONFIG['ACCESSIBILITY']:
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.a11y += [
|
||||
'COMPtrTypes.h',
|
||||
'DocAccessibleChild.h',
|
||||
'HandlerProvider.h',
|
||||
'PlatformChild.h',
|
||||
|
@ -88,6 +88,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
|
||||
testAttrs("statusChild", {"container-live": "polite"}, true);
|
||||
testAttrs("timerChild", {"container-live": "off"}, true);
|
||||
testAbsentAttrs("tablistChild", {"container-live": "polite"});
|
||||
testAttrs("containerLiveOutput", {"container-live": "polite"}, true);
|
||||
testAttrs("containerLiveOutput1", {"container-live": "polite"}, true);
|
||||
testAttrs("containerLiveOutput2", {"container-live": "polite"}, true);
|
||||
|
||||
// container-live-role object attribute
|
||||
testAttrs("log", {"container-live-role": "log"}, true);
|
||||
@ -121,7 +124,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
|
||||
testAttrs("search", {"text-input-type": "search"}, true);
|
||||
testAttrs("tel", {"text-input-type": "tel"}, true);
|
||||
testAttrs("url", {"text-input-type": "url"}, true);
|
||||
testAttrs(getAccessible("number").firstChild, {"text-input-type": "number"}, true);
|
||||
testAttrs("number", {"text-input-type": "number"}, true);
|
||||
|
||||
// ARIA
|
||||
testAttrs("searchbox", {"text-input-type": "search"}, true);
|
||||
@ -166,6 +169,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<!-- container live -->
|
||||
<output id="containerLiveOutput"><div id="containerLiveOutput1"><div id="containerLiveOutput2">Test</div></div></output>
|
||||
|
||||
<!-- aria -->
|
||||
<div id="atomic" aria-atomic="true">live region</div>
|
||||
<div id="atomic_false" aria-atomic="false">live region</div>
|
||||
|
@ -190,7 +190,10 @@
|
||||
|
||||
obj = {
|
||||
role: ROLE_PARAGRAPH,
|
||||
children: [ { role: ROLE_WHITESPACE } ],
|
||||
children: [
|
||||
{ role: ROLE_WHITESPACE },
|
||||
{ role: ROLE_WHITESPACE }
|
||||
]
|
||||
};
|
||||
testElm("br_container", obj);
|
||||
|
||||
@ -707,25 +710,9 @@
|
||||
|
||||
obj = {
|
||||
role: ROLE_SPINBUTTON,
|
||||
interfaces: [ nsIAccessibleValue ],
|
||||
interfaces: [ nsIAccessibleValue, nsIAccessibleText, nsIAccessibleEditableText ],
|
||||
children: [
|
||||
{
|
||||
role: ROLE_ENTRY,
|
||||
extraStates: EXT_STATE_EDITABLE | EXT_STATE_SINGLE_LINE,
|
||||
actions: "activate",
|
||||
interfaces: [ nsIAccessibleText, nsIAccessibleEditableText ],
|
||||
children: [
|
||||
{ role: ROLE_TEXT_LEAF },
|
||||
],
|
||||
},
|
||||
{
|
||||
role: ROLE_PUSHBUTTON,
|
||||
actions: "press",
|
||||
},
|
||||
{
|
||||
role: ROLE_PUSHBUTTON,
|
||||
actions: "press",
|
||||
},
|
||||
{ role: ROLE_TEXT_LEAF },
|
||||
],
|
||||
};
|
||||
testElm("input_number", obj);
|
||||
@ -1114,7 +1101,7 @@
|
||||
// HTML:output
|
||||
|
||||
obj = {
|
||||
role: ROLE_SECTION,
|
||||
role: ROLE_STATUSBAR,
|
||||
attributes: { "live": "polite" },
|
||||
todo_relations: {
|
||||
RELATION_CONTROLLED_BY: "output_input",
|
||||
@ -1428,7 +1415,7 @@
|
||||
<p>This is a quotation taken from the Mozilla Developer Center.</p>
|
||||
</blockquote>
|
||||
|
||||
<!-- two BRs, one will be eaten -->
|
||||
<!-- two BRs, both will be present -->
|
||||
<p id="br_container"><br><br></p>
|
||||
|
||||
<button id="button">button</button>
|
||||
|
@ -171,6 +171,8 @@
|
||||
let shadowSelect = getAccessible("selectShadow").firstChild;
|
||||
gQueue.push(new changeSelectValue(shadowSelect, "VK_DOWN", "2"));
|
||||
|
||||
gQueue.push(new changeValue("number", "2"));
|
||||
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
|
||||
@ -269,5 +271,7 @@
|
||||
select.appendChild(option);
|
||||
shadow.appendChild(select);
|
||||
</script>
|
||||
|
||||
<input type="number" id="number" value="1">
|
||||
</body>
|
||||
</html>
|
||||
|
@ -112,12 +112,12 @@
|
||||
|
||||
two words
|
||||
</div>
|
||||
<div id="dbr3">oneword<br/><br/>two words<br/><br/></div>
|
||||
<div id="dbr3">oneword<br/><br/>two words<br/></div>
|
||||
<div id="e3" contenteditable="true">oneword
|
||||
|
||||
two words
|
||||
</div>
|
||||
<div id="ebr3" contenteditable="true">oneword<br/><br/>two words<br/><br/></div>
|
||||
<div id="ebr3" contenteditable="true">oneword<br/><br/>two words<br/></div>
|
||||
<textarea id="t3" cols="300">oneword
|
||||
|
||||
two words
|
||||
|
@ -84,7 +84,7 @@
|
||||
testTextAtOffset(2, nsIAccessibleText.BOUNDARY_CHAR, "o", 2, 3, "testbr",
|
||||
kOk, kOk, kOk);
|
||||
testTextAtOffset(2, nsIAccessibleText.BOUNDARY_WORD_START, "foo\n", 0, 4,
|
||||
"testbr", kTodo, kOk, kTodo);
|
||||
"testbr", kOk, kOk, kOk);
|
||||
testTextBeforeOffset(2, nsIAccessibleText.BOUNDARY_LINE_START, "foo\n",
|
||||
0, 4, "testbr", kTodo, kOk, kTodo);
|
||||
|
||||
|
@ -106,10 +106,10 @@
|
||||
|
||||
testTextAtOffset([ getAccessible("ht_2").firstChild.firstChild ],
|
||||
BOUNDARY_LINE_START,
|
||||
[ [ 0, 3, "foo", 0, 3 ] ]);
|
||||
[ [ 0, 3, "foo\n", 0, 4 ] ]);
|
||||
testTextAtOffset([ getAccessible("ht_3").firstChild.firstChild ],
|
||||
BOUNDARY_LINE_START,
|
||||
[ [ 0, 3, "foo\n", 0, 4 ], [ 4, 4, "", 4, 4 ] ]);
|
||||
[ [ 0, 3, "foo\n", 0, 4 ], [ 4, 4, "\n", 4, 5 ] ]);
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
// 'Hello world ' (\n is rendered as space)
|
||||
@ -211,12 +211,12 @@
|
||||
|
||||
two words
|
||||
</div>
|
||||
<div id="ml_divbr" style="border-style:outset;">oneword<br/><br/>two words<br/><br/></div>
|
||||
<div id="ml_divbr" style="border-style:outset;">oneword<br/><br/>two words<br/></div>
|
||||
<div id="ml_editable" style="border-style:outset;" contenteditable="true">oneword
|
||||
|
||||
two words
|
||||
</div>
|
||||
<div id="ml_editablebr" contenteditable="true" style="border-style:outset;">oneword<br/><br/>two words<br/><br/></div>
|
||||
<div id="ml_editablebr" contenteditable="true" style="border-style:outset;">oneword<br/><br/>two words<br/></div>
|
||||
<textarea id="ml_textarea" cols="300">oneword
|
||||
|
||||
two words
|
||||
|
@ -305,12 +305,12 @@
|
||||
|
||||
two words
|
||||
</div>
|
||||
<div id="ml_divbr1">oneword<br/><br/>two words<br/><br/></div>
|
||||
<div id="ml_divbr1">oneword<br/><br/>two words<br/></div>
|
||||
<div id="ml_ediv1" contenteditable="true">oneword
|
||||
|
||||
two words
|
||||
</div>
|
||||
<div id="ml_edivbr1" contenteditable="true">oneword<br/><br/>two words<br/><br/></div>
|
||||
<div id="ml_edivbr1" contenteditable="true">oneword<br/><br/>two words<br/></div>
|
||||
<textarea id="ml_t1" cols="300">oneword
|
||||
|
||||
two words
|
||||
|
@ -126,6 +126,12 @@
|
||||
];
|
||||
|
||||
this.invoke = function changeDOMSelection_invoke() {
|
||||
// HyperTextAccessible::GetSelectionDOMRanges ignores hidden selections.
|
||||
// Here we may be focusing an editable element (and thus hiding the
|
||||
// main document selection), so blur it so that we test what we want to
|
||||
// test.
|
||||
document.activeElement.blur();
|
||||
|
||||
var sel = window.getSelection();
|
||||
var range = document.createRange();
|
||||
range.setStart(getNode(aNodeID1), aNodeOffset1);
|
||||
|
@ -199,7 +199,11 @@ function doTest() {
|
||||
{ TEXT_LEAF: [] }, // text
|
||||
], // end children first line
|
||||
}, // end first line
|
||||
{ SECTION: [] }, // second, blank, line
|
||||
{ role: ROLE_SECTION, // Second line
|
||||
children: [
|
||||
{ WHITESPACE: [] }, // whitespace
|
||||
], // end children second line
|
||||
}, // end second line
|
||||
{ role: ROLE_SECTION, // Third line
|
||||
children: [
|
||||
{ TEXT_LEAF: [] }, // text
|
||||
|
@ -62,17 +62,12 @@
|
||||
testAccessibleTree("range", accTree);
|
||||
|
||||
// input@type="number"
|
||||
accTree =
|
||||
{ SPINBUTTON: [
|
||||
{ ENTRY: [ ] },
|
||||
{ PUSHBUTTON: [ ] },
|
||||
{ PUSHBUTTON: [ ] },
|
||||
] };
|
||||
accTree = { SPINBUTTON: [ ] };
|
||||
testAccessibleTree("number", accTree);
|
||||
|
||||
// output
|
||||
accTree = {
|
||||
role: ROLE_SECTION,
|
||||
role: ROLE_STATUSBAR,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_TEXT_LEAF,
|
||||
|
@ -166,6 +166,63 @@
|
||||
|
||||
testAccessibleTree("list10", tree);
|
||||
|
||||
// list-style-image
|
||||
testAccessibleTree("list11", discAccTree);
|
||||
|
||||
// list-style: none
|
||||
tree =
|
||||
{ LIST: [ // ul
|
||||
{ LISTITEM: [ // li
|
||||
{ TEXT_LEAF: [] },
|
||||
] },
|
||||
{ LISTITEM: [ // li
|
||||
{ TEXT_LEAF: [] },
|
||||
] },
|
||||
] };
|
||||
testAccessibleTree("list12", tree);
|
||||
|
||||
// ::marker with content
|
||||
tree = { // ol
|
||||
role: ROLE_LIST,
|
||||
children: [
|
||||
{ // li
|
||||
role: ROLE_LISTITEM,
|
||||
children: [
|
||||
{ // ::marker content text
|
||||
role: ROLE_STATICTEXT,
|
||||
name: "foo",
|
||||
},
|
||||
{ // ::marker content counter
|
||||
role: ROLE_STATICTEXT,
|
||||
name: "1",
|
||||
},
|
||||
{
|
||||
role: ROLE_TEXT_LEAF,
|
||||
name: "Oranges",
|
||||
},
|
||||
],
|
||||
},
|
||||
{ // li
|
||||
role: ROLE_LISTITEM,
|
||||
children: [
|
||||
{ // ::marker content text
|
||||
role: ROLE_STATICTEXT,
|
||||
name: "foo",
|
||||
},
|
||||
{ // ::marker content counter
|
||||
role: ROLE_STATICTEXT,
|
||||
name: "2",
|
||||
},
|
||||
{
|
||||
role: ROLE_TEXT_LEAF,
|
||||
name: "Apples",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
testAccessibleTree("list13", tree);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
@ -266,5 +323,32 @@
|
||||
<div><dt>item2</td><dd>description</dd></div>
|
||||
</dl>
|
||||
|
||||
<!-- list-style-image -->
|
||||
<ul id="list11"
|
||||
style="list-style-type: none; list-style-image: url('../moz.png');">
|
||||
<li>Oranges</li>
|
||||
<li>Apples</li>
|
||||
<li>Bananas</li>
|
||||
</ul>
|
||||
|
||||
<!-- list-style: none -->
|
||||
<ul id="list12" style="list-style: none;">
|
||||
<li>Oranges</li>
|
||||
<li>Apples</li>
|
||||
</ul>
|
||||
|
||||
<!-- ::marker with content -->
|
||||
<style>
|
||||
#list13 li {
|
||||
counter-increment: list13counter;
|
||||
}
|
||||
#list13 li::marker {
|
||||
content: 'foo' counter(list13counter);
|
||||
}
|
||||
</style>
|
||||
<ol id="list13">
|
||||
<li>Oranges</li>
|
||||
<li>Apples</li>
|
||||
</ol>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -115,7 +115,7 @@ sdnTextAccessible::scrollToSubstring(unsigned int aStartIndex,
|
||||
unsigned int aEndIndex) {
|
||||
if (mAccessible->IsDefunct()) return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
RefPtr<nsRange> range = new nsRange(mAccessible->GetContent());
|
||||
RefPtr<nsRange> range = nsRange::Create(mAccessible->GetContent());
|
||||
if (NS_FAILED(range->SetStart(mAccessible->GetContent(), aStartIndex)))
|
||||
return E_FAIL;
|
||||
|
||||
|
@ -109,7 +109,7 @@ uint64_t XULMenuitemAccessible::NativeInteractiveState() const {
|
||||
if (!menuFrame || !menuFrame->IsOnMenuBar()) {
|
||||
skipNavigatingDisabledMenuItem =
|
||||
LookAndFeel::GetInt(
|
||||
LookAndFeel::eIntID_SkipNavigatingDisabledMenuItem, 0) != 0;
|
||||
LookAndFeel::IntID::SkipNavigatingDisabledMenuItem, 0) != 0;
|
||||
}
|
||||
|
||||
if (skipNavigatingDisabledMenuItem) return states::UNAVAILABLE;
|
||||
|
@ -437,7 +437,7 @@ Accessible* XULTreeAccessible::GetTreeItemAccessible(int32_t aRow) const {
|
||||
|
||||
RefPtr<Accessible> treeItem = CreateTreeItemAccessible(aRow);
|
||||
if (treeItem) {
|
||||
mAccessibleCache.Put(key, treeItem);
|
||||
mAccessibleCache.Put(key, RefPtr{treeItem});
|
||||
Document()->BindToDocument(treeItem, nullptr);
|
||||
return treeItem;
|
||||
}
|
||||
|
@ -303,7 +303,7 @@ XULTreeGridCellAccessible* XULTreeGridRowAccessible::GetCellAccessible(
|
||||
RefPtr<XULTreeGridCellAccessible> cell = new XULTreeGridCellAccessibleWrap(
|
||||
mContent, mDoc, const_cast<XULTreeGridRowAccessible*>(this), mTree,
|
||||
mTreeView, mRow, aColumn);
|
||||
mAccessibleCache.Put(key, cell);
|
||||
mAccessibleCache.Put(key, RefPtr{cell});
|
||||
Document()->BindToDocument(cell, nullptr);
|
||||
return cell;
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ class ClickHandlerChild extends ActorChild {
|
||||
Ci.nsIReferrerInfo
|
||||
);
|
||||
if (node) {
|
||||
referrerInfo.initWithNode(node);
|
||||
referrerInfo.initWithElement(node);
|
||||
} else {
|
||||
referrerInfo.initWithDocument(ownerDoc);
|
||||
}
|
||||
|
@ -586,7 +586,7 @@ class ContextMenuChild extends ActorChild {
|
||||
let referrerInfo = Cc["@mozilla.org/referrer-info;1"].createInstance(
|
||||
Ci.nsIReferrerInfo
|
||||
);
|
||||
referrerInfo.initWithNode(
|
||||
referrerInfo.initWithElement(
|
||||
context.onLink ? context.link : aEvent.composedTarget
|
||||
);
|
||||
|
||||
@ -659,7 +659,7 @@ class ContextMenuChild extends ActorChild {
|
||||
"@mozilla.org/referrer-info;1"
|
||||
].createInstance(Ci.nsIReferrerInfo);
|
||||
|
||||
targetReferrerInfo.initWithNode(aEvent.composedTarget);
|
||||
targetReferrerInfo.initWithElement(aEvent.composedTarget);
|
||||
data.targetReferrerInfo = E10SUtils.serializeReferrerInfo(
|
||||
targetReferrerInfo
|
||||
);
|
||||
|
@ -365,13 +365,6 @@ pref("permissions.default.shortcuts", 0);
|
||||
|
||||
pref("permissions.postPrompt.animate", true);
|
||||
|
||||
// This is primarily meant to be enabled for studies.
|
||||
#ifdef NIGHTLY_BUILD
|
||||
pref("permissions.eventTelemetry.enabled", true);
|
||||
#else
|
||||
pref("permissions.eventTelemetry.enabled", false);
|
||||
#endif
|
||||
|
||||
#ifdef NIGHTLY_BUILD
|
||||
pref("permissions.delegation.enable", true);
|
||||
#else
|
||||
@ -1400,11 +1393,6 @@ pref("identity.fxaccounts.commands.enabled", true);
|
||||
// Default is 24 hours.
|
||||
pref("identity.fxaccounts.commands.missed.fetch_interval", 86400);
|
||||
|
||||
// On GTK, we now default to showing the menubar only when alt is pressed:
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
pref("ui.key.menuAccessKeyFocuses", true);
|
||||
#endif
|
||||
|
||||
// Whether we should run a test-pattern through EME GMPs before assuming they'll
|
||||
// decode H.264.
|
||||
pref("media.gmp.trial-create.enabled", true);
|
||||
@ -1437,11 +1425,6 @@ pref("media.autoplay.default", 1); // 0=Allowed, 1=Blocked, 5=All Blocked
|
||||
pref("media.autoplay.block-webaudio", false);
|
||||
#endif
|
||||
|
||||
// Play with different values of the decay time and get telemetry,
|
||||
// 0 means to randomize (and persist) the experiment value in users' profiles,
|
||||
// -1 means no experiment is run and we use the preferred value for frecency (6h)
|
||||
pref("browser.cache.frecency_experiment", 0);
|
||||
|
||||
pref("browser.translation.detectLanguage", false);
|
||||
pref("browser.translation.neverForLanguages", "");
|
||||
// Show the translation UI bits, like the info bar, notification icon and preferences.
|
||||
@ -1704,14 +1687,6 @@ pref("fission.frontend.simulate-events", false);
|
||||
// their destination (using the BrowsingContext id).
|
||||
pref("fission.frontend.simulate-messages", false);
|
||||
|
||||
// Prio preferences
|
||||
// Only enable by default on Nightly.
|
||||
// On platforms that do not build libprio, do not set these prefs at all, which gives us a way to detect support.
|
||||
|
||||
// Curve25519 public keys for Prio servers
|
||||
pref("prio.publicKeyA", "35AC1C7576C7C6EDD7FED6BCFC337B34D48CB4EE45C86BEEFB40BD8875707733");
|
||||
pref("prio.publicKeyB", "26E6674E65425B823F1F1D5F96E3BB3EF9E406EC7FBA7DEF8B08A35DD135AF50");
|
||||
|
||||
// Coverage ping is disabled by default.
|
||||
pref("toolkit.coverage.enabled", false);
|
||||
pref("toolkit.coverage.endpoint.base", "data:text/plain,");
|
||||
|
@ -10,7 +10,7 @@
|
||||
var gIdentityHandler = {
|
||||
/**
|
||||
* nsIURI for which the identity UI is displayed. This has been already
|
||||
* processed by nsIURIFixup.createExposableURI.
|
||||
* processed by createExposableURI.
|
||||
*/
|
||||
_uri: null,
|
||||
|
||||
@ -448,7 +448,7 @@ var gIdentityHandler = {
|
||||
* Bitmask provided by nsIWebProgressListener.onSecurityChange.
|
||||
* @param uri
|
||||
* nsIURI for which the identity UI should be displayed, already
|
||||
* processed by nsIURIFixup.createExposableURI.
|
||||
* processed by createExposableURI.
|
||||
*/
|
||||
updateIdentity(state, uri) {
|
||||
let shouldHidePopup = this._uri && this._uri.spec != uri.spec;
|
||||
|
@ -3285,7 +3285,7 @@ function URLBarSetURI(aURI, updatePopupNotifications) {
|
||||
let uri = aURI || gBrowser.currentURI;
|
||||
// Strip off usernames and passwords for the location bar
|
||||
try {
|
||||
uri = Services.uriFixup.createExposableURI(uri);
|
||||
uri = Services.io.createExposableURI(uri);
|
||||
} catch (e) {}
|
||||
|
||||
// Replace initial page URIs with an empty string
|
||||
@ -5570,7 +5570,7 @@ var XULBrowserWindow = {
|
||||
|
||||
setOverLink(url, anchorElt) {
|
||||
if (url) {
|
||||
url = Services.textToSubURI.unEscapeURIForUI("UTF-8", url);
|
||||
url = Services.textToSubURI.unEscapeURIForUI(url);
|
||||
|
||||
// Encode bidirectional formatting characters.
|
||||
// (RFC 3987 sections 3.2 and 4.1 paragraph 6)
|
||||
@ -6000,7 +6000,7 @@ var XULBrowserWindow = {
|
||||
gURLBarHandler.formatValue();
|
||||
|
||||
try {
|
||||
uri = Services.uriFixup.createExposableURI(uri);
|
||||
uri = Services.io.createExposableURI(uri);
|
||||
} catch (e) {}
|
||||
gIdentityHandler.updateIdentity(this._state, uri);
|
||||
},
|
||||
@ -7508,7 +7508,7 @@ function handleLinkClick(event, href, linkNode) {
|
||||
Ci.nsIReferrerInfo
|
||||
);
|
||||
if (linkNode) {
|
||||
referrerInfo.initWithNode(linkNode);
|
||||
referrerInfo.initWithElement(linkNode);
|
||||
} else {
|
||||
referrerInfo.initWithDocument(doc);
|
||||
}
|
||||
|
@ -1785,10 +1785,7 @@ nsContextMenu.prototype = {
|
||||
// Let's try to unescape it using a character set
|
||||
// in case the address is not ASCII.
|
||||
try {
|
||||
addresses = Services.textToSubURI.unEscapeURIForUI(
|
||||
gContextMenuContentData.charSet,
|
||||
addresses
|
||||
);
|
||||
addresses = Services.textToSubURI.unEscapeURIForUI(addresses);
|
||||
} catch (ex) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
@ -9,6 +9,10 @@
|
||||
/* import-globals-from permissions.js */
|
||||
/* import-globals-from security.js */
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
E10SUtils: "resource://gre/modules/E10SUtils.jsm",
|
||||
});
|
||||
|
||||
// define a js object to implement nsITreeView
|
||||
function pageInfoTreeView(treeid, copycol) {
|
||||
// copycol is the index number for the column that we want to add to
|
||||
@ -955,10 +959,7 @@ function makePreview(row) {
|
||||
var width = 0,
|
||||
height = 0;
|
||||
|
||||
let serial = Cc["@mozilla.org/network/serialization-helper;1"].getService(
|
||||
Ci.nsISerializationHelper
|
||||
);
|
||||
let triggeringPrinStr = serial.serializeToString(gDocInfo.principal);
|
||||
let triggeringPrinStr = E10SUtils.serializePrincipal(gDocInfo.principal);
|
||||
if (
|
||||
(item.HTMLLinkElement ||
|
||||
item.HTMLInputElement ||
|
||||
|
@ -1001,7 +1001,7 @@
|
||||
// XXX https://bugzilla.mozilla.org/show_bug.cgi?id=22183#c239
|
||||
try {
|
||||
if (docElement.getAttribute("chromehidden").includes("location")) {
|
||||
var uri = Services.uriFixup.createExposableURI(aBrowser.currentURI);
|
||||
var uri = Services.io.createExposableURI(aBrowser.currentURI);
|
||||
if (uri.scheme == "about") {
|
||||
newTitle = uri.spec + sep + newTitle;
|
||||
} else {
|
||||
@ -1494,7 +1494,7 @@
|
||||
// See if we can use the URI as the title.
|
||||
if (browser.currentURI.displaySpec) {
|
||||
try {
|
||||
title = Services.uriFixup.createExposableURI(browser.currentURI)
|
||||
title = Services.io.createExposableURI(browser.currentURI)
|
||||
.displaySpec;
|
||||
} catch (ex) {
|
||||
title = browser.currentURI.displaySpec;
|
||||
|
@ -2,3 +2,5 @@
|
||||
|
||||
[browser_principalSerialization_version1.js]
|
||||
[browser_principalSerialization_csp.js]
|
||||
[browser_principalSerialization_json.js]
|
||||
skip-if = debug # deliberately bypass assertions when deserializing. Bug 965637 removed the CSP from Principals, but the remaining bits in such Principals should deserialize correctly.
|
||||
|
@ -0,0 +1,164 @@
|
||||
"use strict";
|
||||
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*
|
||||
This test file exists to ensure whenever changes to principal serialization happens,
|
||||
we guarantee that the data can be restored and generated into a new principal.
|
||||
|
||||
The tests are written to be brittle so we encode all versions of the changes into the tests.
|
||||
*/
|
||||
|
||||
add_task(async function test_nullPrincipal() {
|
||||
const nullId = "0";
|
||||
// fields
|
||||
const uri = 0;
|
||||
const suffix = 1;
|
||||
|
||||
const nullReplaceRegex = /moz-nullprincipal:{[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}}/;
|
||||
const NULL_REPLACE = "NULL_PRINCIPAL_URL";
|
||||
|
||||
/*
|
||||
This test should NOT be resilient to changes in versioning,
|
||||
however it exists purely to verify the code doesn't unintentionally change without updating versioning and migration code.
|
||||
*/
|
||||
let tests = [
|
||||
{
|
||||
input: { OA: {} },
|
||||
expected: `{"${nullId}":{"${uri}":"${NULL_REPLACE}"}}`,
|
||||
},
|
||||
{
|
||||
input: { OA: {} },
|
||||
expected: `{"${nullId}":{"${uri}":"${NULL_REPLACE}"}}`,
|
||||
},
|
||||
{
|
||||
input: { OA: { userContextId: 0 } },
|
||||
expected: `{"${nullId}":{"${uri}":"${NULL_REPLACE}"}}`,
|
||||
},
|
||||
{
|
||||
input: { OA: { userContextId: 2 } },
|
||||
expected: `{"${nullId}":{"${uri}":"${NULL_REPLACE}","${suffix}":"^userContextId=2"}}`,
|
||||
},
|
||||
{
|
||||
input: { OA: { privateBrowsingId: 1 } },
|
||||
expected: `{"${nullId}":{"${uri}":"${NULL_REPLACE}","${suffix}":"^privateBrowsingId=1"}}`,
|
||||
},
|
||||
{
|
||||
input: { OA: { privateBrowsingId: 0 } },
|
||||
expected: `{"${nullId}":{"${uri}":"${NULL_REPLACE}"}}`,
|
||||
},
|
||||
];
|
||||
|
||||
for (let test of tests) {
|
||||
let p = Services.scriptSecurityManager.createNullPrincipal(test.input.OA);
|
||||
let sp = E10SUtils.serializePrincipal(p);
|
||||
// Not sure why cppjson is adding a \n here
|
||||
let spr = atob(sp).replace(nullReplaceRegex, NULL_REPLACE);
|
||||
is(
|
||||
test.expected,
|
||||
spr,
|
||||
"Expected serialized object for " + JSON.stringify(test.input)
|
||||
);
|
||||
let dp = E10SUtils.deserializePrincipal(sp);
|
||||
|
||||
// Check all the origin attributes
|
||||
for (let key in test.input.OA) {
|
||||
is(
|
||||
dp.originAttributes[key],
|
||||
test.input.OA[key],
|
||||
"Ensure value of " + key + " is " + test.input.OA[key]
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function test_contentPrincipal() {
|
||||
const contentId = "1";
|
||||
// fields
|
||||
const codebase = 0;
|
||||
// const domain = 1;
|
||||
const suffix = 2;
|
||||
// const csp = 3;
|
||||
|
||||
/*
|
||||
This test should NOT be resilient to changes in versioning,
|
||||
however it exists purely to verify the code doesn't unintentionally change without updating versioning and migration code.
|
||||
*/
|
||||
let tests = [
|
||||
{
|
||||
input: { uri: "http://example.com/", OA: {} },
|
||||
expected: `{"${contentId}":{"${codebase}":"http://example.com/"}}`,
|
||||
},
|
||||
{
|
||||
input: { uri: "http://mozilla1.com/", OA: {} },
|
||||
expected: `{"${contentId}":{"${codebase}":"http://mozilla1.com/"}}`,
|
||||
},
|
||||
{
|
||||
input: { uri: "http://mozilla2.com/", OA: { userContextId: 0 } },
|
||||
expected: `{"${contentId}":{"${codebase}":"http://mozilla2.com/"}}`,
|
||||
},
|
||||
{
|
||||
input: { uri: "http://mozilla3.com/", OA: { userContextId: 2 } },
|
||||
expected: `{"${contentId}":{"${codebase}":"http://mozilla3.com/","${suffix}":"^userContextId=2"}}`,
|
||||
},
|
||||
{
|
||||
input: { uri: "http://mozilla4.com/", OA: { privateBrowsingId: 1 } },
|
||||
expected: `{"${contentId}":{"${codebase}":"http://mozilla4.com/","${suffix}":"^privateBrowsingId=1"}}`,
|
||||
},
|
||||
{
|
||||
input: { uri: "http://mozilla5.com/", OA: { privateBrowsingId: 0 } },
|
||||
expected: `{"${contentId}":{"${codebase}":"http://mozilla5.com/"}}`,
|
||||
},
|
||||
];
|
||||
|
||||
for (let test of tests) {
|
||||
let uri = Services.io.newURI(test.input.uri);
|
||||
let p = Services.scriptSecurityManager.createCodebasePrincipal(
|
||||
uri,
|
||||
test.input.OA
|
||||
);
|
||||
let sp = E10SUtils.serializePrincipal(p);
|
||||
is(
|
||||
test.expected,
|
||||
atob(sp),
|
||||
"Expected serialized object for " + test.input.uri
|
||||
);
|
||||
is(
|
||||
btoa(test.expected),
|
||||
sp,
|
||||
"Expected serialized string for " + test.input.uri
|
||||
);
|
||||
let dp = E10SUtils.deserializePrincipal(sp);
|
||||
is(dp.URI.spec, test.input.uri, "Ensure spec is the same");
|
||||
|
||||
// Check all the origin attributes
|
||||
for (let key in test.input.OA) {
|
||||
is(
|
||||
dp.originAttributes[key],
|
||||
test.input.OA[key],
|
||||
"Ensure value of " + key + " is " + test.input.OA[key]
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function test_systemPrincipal() {
|
||||
const systemId = "3";
|
||||
/*
|
||||
This test should NOT be resilient to changes in versioning,
|
||||
however it exists purely to verify the code doesn't unintentionally change without updating versioning and migration code.
|
||||
*/
|
||||
const expected = `{"${systemId}":{}}`;
|
||||
|
||||
let p = Services.scriptSecurityManager.getSystemPrincipal();
|
||||
let sp = E10SUtils.serializePrincipal(p);
|
||||
is(expected, atob(sp), "Expected serialized object for system principal");
|
||||
is(btoa(expected), sp, "Expected serialized string for system principal");
|
||||
let dp = E10SUtils.deserializePrincipal(sp);
|
||||
is(
|
||||
dp,
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
"Deserialized the system principal"
|
||||
);
|
||||
});
|
@ -39,66 +39,6 @@ add_task(function test_nullPrincipal() {
|
||||
is(p2.originAttributes.userContextId, 2, "Expected a userContextId of 2");
|
||||
});
|
||||
|
||||
add_task(async function test_contentPrincipal() {
|
||||
/*
|
||||
This test should NOT be resilient to changes in versioning,
|
||||
however it exists purely to verify the code doesn't unintentionally change without updating versioning and migration code.
|
||||
*/
|
||||
let tests = [
|
||||
{
|
||||
input: ["http://example.com/", {}],
|
||||
expected:
|
||||
"ZT4OTT7kRfqycpfCC8AeuAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAFABAAAAE2h0dHA6Ly9leGFtcGxlLmNvbS8AAAAAAAAABAAAAAcAAAALAAAAB/////8AAAAH/////wAAAAcAAAALAAAAEgAAAAEAAAASAAAAAQAAABIAAAABAAAAEwAAAAAAAAAT/////wAAAAD/////AAAAEv////8AAAAS/////wEAAAAAAAAAAAAAAAA=",
|
||||
},
|
||||
{
|
||||
input: ["http://mozilla1.com/", {}],
|
||||
expected:
|
||||
"ZT4OTT7kRfqycpfCC8AeuAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAFABAAAAFGh0dHA6Ly9tb3ppbGxhMS5jb20vAAAAAAAAAAQAAAAHAAAADAAAAAf/////AAAAB/////8AAAAHAAAADAAAABMAAAABAAAAEwAAAAEAAAATAAAAAQAAABQAAAAAAAAAFP////8AAAAA/////wAAABP/////AAAAE/////8BAAAAAAAAAAAAAAAA",
|
||||
},
|
||||
{
|
||||
input: ["http://mozilla2.com/", { userContextId: 0 }],
|
||||
expected:
|
||||
"ZT4OTT7kRfqycpfCC8AeuAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAFABAAAAFGh0dHA6Ly9tb3ppbGxhMi5jb20vAAAAAAAAAAQAAAAHAAAADAAAAAf/////AAAAB/////8AAAAHAAAADAAAABMAAAABAAAAEwAAAAEAAAATAAAAAQAAABQAAAAAAAAAFP////8AAAAA/////wAAABP/////AAAAE/////8BAAAAAAAAAAAAAAAA",
|
||||
},
|
||||
{
|
||||
input: ["http://mozilla3.com/", { userContextId: 2 }],
|
||||
expected:
|
||||
"ZT4OTT7kRfqycpfCC8AeuAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAFABAAAAFGh0dHA6Ly9tb3ppbGxhMy5jb20vAAAAAAAAAAQAAAAHAAAADAAAAAf/////AAAAB/////8AAAAHAAAADAAAABMAAAABAAAAEwAAAAEAAAATAAAAAQAAABQAAAAAAAAAFP////8AAAAA/////wAAABP/////AAAAE/////8BAAAAAAAAAAAAABBedXNlckNvbnRleHRJZD0yAA==",
|
||||
},
|
||||
{
|
||||
input: ["http://mozilla4.com/", { privateBrowsingId: 1 }],
|
||||
expected:
|
||||
"ZT4OTT7kRfqycpfCC8AeuAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAFABAAAAFGh0dHA6Ly9tb3ppbGxhNC5jb20vAAAAAAAAAAQAAAAHAAAADAAAAAf/////AAAAB/////8AAAAHAAAADAAAABMAAAABAAAAEwAAAAEAAAATAAAAAQAAABQAAAAAAAAAFP////8AAAAA/////wAAABP/////AAAAE/////8BAAAAAAAAAAAAABRecHJpdmF0ZUJyb3dzaW5nSWQ9MQA=",
|
||||
},
|
||||
{
|
||||
input: ["http://mozilla5.com/", { privateBrowsingId: 0 }],
|
||||
expected:
|
||||
"ZT4OTT7kRfqycpfCC8AeuAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAFABAAAAFGh0dHA6Ly9tb3ppbGxhNS5jb20vAAAAAAAAAAQAAAAHAAAADAAAAAf/////AAAAB/////8AAAAHAAAADAAAABMAAAABAAAAEwAAAAEAAAATAAAAAQAAABQAAAAAAAAAFP////8AAAAA/////wAAABP/////AAAAE/////8BAAAAAAAAAAAAAAAA",
|
||||
},
|
||||
];
|
||||
|
||||
for (let test of tests) {
|
||||
let uri = Services.io.newURI(test.input[0]);
|
||||
let p = Services.scriptSecurityManager.createCodebasePrincipal(
|
||||
uri,
|
||||
test.input[1]
|
||||
);
|
||||
let sp = E10SUtils.serializePrincipal(p);
|
||||
is(test.expected, sp, "Expected serialized string for " + test.input[0]);
|
||||
let dp = E10SUtils.deserializePrincipal(sp);
|
||||
is(dp.URI.spec, test.input[0], "Ensure spec is the same");
|
||||
|
||||
// Check all the origin attributes
|
||||
for (let key in test.input[1]) {
|
||||
is(
|
||||
dp.originAttributes[key],
|
||||
test.input[1][key],
|
||||
"Ensure value of " + key + " is " + test.input[1][key]
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function test_realHistoryCheck() {
|
||||
/*
|
||||
This test should be resilient to changes in principal serialization, if these are failing then it's likely the code will break session storage.
|
||||
|
@ -10,18 +10,6 @@ add_task(async function() {
|
||||
await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
|
||||
// Push the state before maximizing the window and clicking below.
|
||||
content.history.pushState("page2", "page2", "page2");
|
||||
|
||||
// While in the child process, add a listener for the popstate event here. This
|
||||
// event will fire when the mouse click happens.
|
||||
content.addEventListener(
|
||||
"popstate",
|
||||
function() {
|
||||
sendAsyncMessage("Test:PopStateOccurred", {
|
||||
location: content.document.location.href,
|
||||
});
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
});
|
||||
|
||||
window.maximize();
|
||||
@ -32,23 +20,16 @@ add_task(async function() {
|
||||
var yPixel = boundingRect.top + Math.floor(boundingRect.height / 2);
|
||||
var xPixel = 0; // Use the first pixel of the screen since it is maximized.
|
||||
|
||||
let resultLocation = await new Promise(resolve => {
|
||||
window.messageManager.addMessageListener(
|
||||
"Test:PopStateOccurred",
|
||||
function statePopped(message) {
|
||||
window.messageManager.removeMessageListener(
|
||||
"Test:PopStateOccurred",
|
||||
statePopped
|
||||
);
|
||||
resolve(message.data.location);
|
||||
}
|
||||
);
|
||||
|
||||
EventUtils.synthesizeMouseAtPoint(xPixel, yPixel, {}, window);
|
||||
});
|
||||
let popStatePromise = BrowserTestUtils.waitForContentEvent(
|
||||
gBrowser.selectedBrowser,
|
||||
"popstate",
|
||||
true
|
||||
);
|
||||
EventUtils.synthesizeMouseAtPoint(xPixel, yPixel, {}, window);
|
||||
await popStatePromise;
|
||||
|
||||
is(
|
||||
resultLocation,
|
||||
gBrowser.selectedBrowser.currentURI.spec,
|
||||
firstLocation,
|
||||
"Clicking the first pixel should have navigated back."
|
||||
);
|
||||
|
@ -40,6 +40,10 @@ registerCleanupFunction(() => {
|
||||
* browser in an e10s window, that the new tab will load properly.
|
||||
*/
|
||||
add_task(async function test_new_tab() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["domsecurity.skip_html_fragment_assertion", true]],
|
||||
});
|
||||
|
||||
let normalWindow = await BrowserTestUtils.openNewBrowserWindow({
|
||||
remote: true,
|
||||
});
|
||||
@ -84,6 +88,10 @@ add_task(async function test_new_tab() {
|
||||
* window. Also tests with a private browsing window.
|
||||
*/
|
||||
add_task(async function test_new_window() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["domsecurity.skip_html_fragment_assertion", true]],
|
||||
});
|
||||
|
||||
let normalWindow = await BrowserTestUtils.openNewBrowserWindow(
|
||||
{
|
||||
remote: true,
|
||||
|
@ -49,11 +49,8 @@ function testFirstPartyDomain(pageInfo) {
|
||||
}
|
||||
|
||||
// Check the node has the attribute 'triggeringprincipal'.
|
||||
let serial = Cc[
|
||||
"@mozilla.org/network/serialization-helper;1"
|
||||
].getService(Ci.nsISerializationHelper);
|
||||
let loadingPrincipalStr = preview.getAttribute("triggeringprincipal");
|
||||
let loadingPrincipal = serial.deserializeObject(loadingPrincipalStr);
|
||||
let loadingPrincipal = E10SUtils.deserializePrincipal(loadingPrincipalStr);
|
||||
Assert.equal(
|
||||
loadingPrincipal.originAttributes.firstPartyDomain,
|
||||
EXPECTED_DOMAIN,
|
||||
|
@ -291,7 +291,7 @@ const startupPhases = {
|
||||
// bug 975996
|
||||
path: "ProfD:permissions.sqlite",
|
||||
condition: WIN || MAC,
|
||||
fsync: 7,
|
||||
fsync: 8,
|
||||
read: 2,
|
||||
stat: 1,
|
||||
write: 10,
|
||||
@ -300,9 +300,9 @@ const startupPhases = {
|
||||
// bug 975996
|
||||
path: "ProfD:permissions.sqlite-journal",
|
||||
condition: WIN || MAC,
|
||||
fsync: 7,
|
||||
stat: 26,
|
||||
write: 38,
|
||||
fsync: 8,
|
||||
stat: 28,
|
||||
write: 40,
|
||||
},
|
||||
{
|
||||
// bug 975996
|
||||
|
@ -6,7 +6,6 @@ support-files=
|
||||
[browser_canvas_fingerprinting_resistance.js]
|
||||
skip-if = debug || os == "linux" && asan # Bug 1522069
|
||||
[browser_permissions.js]
|
||||
[browser_permissions_event_telemetry.js]
|
||||
[browser_permissions_postPrompt.js]
|
||||
support-files=
|
||||
dummy.js
|
||||
|
@ -1,176 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const ORIGIN = "https://example.com";
|
||||
const PERMISSIONS_PAGE =
|
||||
getRootDirectory(gTestPath).replace("chrome://mochitests/content", ORIGIN) +
|
||||
"permissions.html";
|
||||
|
||||
async function showPermissionPrompt(browser) {
|
||||
let popupshown = BrowserTestUtils.waitForEvent(
|
||||
PopupNotifications.panel,
|
||||
"popupshown"
|
||||
);
|
||||
|
||||
await ContentTask.spawn(browser, null, function() {
|
||||
E10SUtils.wrapHandlingUserInput(content, true, () => {
|
||||
// We need to synthesize the click instead of calling .click(),
|
||||
// otherwise the document will not correctly register the user gesture.
|
||||
let EventUtils = ContentTaskUtils.getEventUtils(content);
|
||||
let notificationButton = content.document.getElementById(
|
||||
"desktop-notification"
|
||||
);
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
notificationButton,
|
||||
{ isSynthesized: false },
|
||||
content
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
await popupshown;
|
||||
|
||||
ok(true, "Notification permission prompt was shown");
|
||||
}
|
||||
|
||||
function checkEventTelemetry(method) {
|
||||
let events = Services.telemetry.snapshotEvents(
|
||||
Ci.nsITelemetry.DATASET_ALL_CHANNELS,
|
||||
true
|
||||
).parent;
|
||||
events = events.filter(
|
||||
e =>
|
||||
e[1] == "security.ui.permissionprompt" &&
|
||||
e[2] == method &&
|
||||
e[3] == "notifications"
|
||||
);
|
||||
is(events.length, 1, "recorded telemetry for showing the prompt");
|
||||
ok(
|
||||
typeof events[0][4] == "string",
|
||||
"recorded a hashed and salted variant of the domain"
|
||||
);
|
||||
is(events[0][4].length * 4, 256, "hash is a 256 bit string");
|
||||
ok(
|
||||
!events[0][4].includes("example.com"),
|
||||
"we're not including the domain by accident"
|
||||
);
|
||||
|
||||
// We assume that even the slowest infra machines are able to show
|
||||
// a permission prompt within five minutes.
|
||||
const FIVE_MINUTES = 1000 * 60 * 5;
|
||||
|
||||
let timeOnPage = Number(events[0][5].timeOnPage);
|
||||
let lastInteraction = Number(events[0][5].lastInteraction);
|
||||
ok(
|
||||
timeOnPage > 0 && timeOnPage < FIVE_MINUTES,
|
||||
`Has recorded time on page (${timeOnPage})`
|
||||
);
|
||||
is(events[0][5].hasUserInput, "true", "Has recorded user input");
|
||||
is(events[0][5].allPermsDenied, "3", "Has recorded total denied permissions");
|
||||
is(
|
||||
events[0][5].allPermsGranted,
|
||||
method == "accept" ? "3" : "2",
|
||||
"Has recorded total granted permissions"
|
||||
);
|
||||
is(
|
||||
events[0][5].thisPermDenied,
|
||||
"0",
|
||||
"Has recorded denied notification permissions"
|
||||
);
|
||||
is(
|
||||
events[0][5].thisPermGranted,
|
||||
method == "accept" ? "2" : "1",
|
||||
"Has recorded granted notification permissions"
|
||||
);
|
||||
is(
|
||||
events[0][5].docHasUserInput,
|
||||
"true",
|
||||
"Has recorded user input on document"
|
||||
);
|
||||
ok(
|
||||
lastInteraction > Date.now() - FIVE_MINUTES && lastInteraction < Date.now(),
|
||||
`Has recorded last user input time (${lastInteraction})`
|
||||
);
|
||||
}
|
||||
|
||||
add_task(async function setup() {
|
||||
let oldCanRecord = Services.telemetry.canRecordExtended;
|
||||
Services.telemetry.canRecordExtended = true;
|
||||
|
||||
Services.prefs.setBoolPref("permissions.eventTelemetry.enabled", true);
|
||||
|
||||
// Add some example permissions.
|
||||
let uri = Services.io.newURI(PERMISSIONS_PAGE);
|
||||
let uri2 = Services.io.newURI("https://example.org");
|
||||
let uri3 = Services.io.newURI("http://sub.example.org");
|
||||
PermissionTestUtils.add(uri, "geo", Services.perms.ALLOW_ACTION);
|
||||
PermissionTestUtils.add(
|
||||
uri3,
|
||||
"desktop-notification",
|
||||
Services.perms.ALLOW_ACTION
|
||||
);
|
||||
PermissionTestUtils.add(uri2, "microphone", Services.perms.DENY_ACTION);
|
||||
PermissionTestUtils.add(uri, "camera", Services.perms.DENY_ACTION);
|
||||
PermissionTestUtils.add(uri2, "geo", Services.perms.DENY_ACTION);
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
Services.perms.removeAll();
|
||||
Services.prefs.clearUserPref("permissions.eventTelemetry.enabled");
|
||||
Services.telemetry.canRecordExtended = oldCanRecord;
|
||||
});
|
||||
|
||||
Services.telemetry.clearEvents();
|
||||
});
|
||||
|
||||
add_task(async function testAccept() {
|
||||
await BrowserTestUtils.withNewTab(PERMISSIONS_PAGE, async function(browser) {
|
||||
await showPermissionPrompt(browser);
|
||||
|
||||
checkEventTelemetry("show");
|
||||
|
||||
let notification = PopupNotifications.panel.firstElementChild;
|
||||
EventUtils.synthesizeMouseAtCenter(notification.button, {});
|
||||
|
||||
checkEventTelemetry("accept");
|
||||
|
||||
Services.telemetry.clearEvents();
|
||||
PermissionTestUtils.remove(PERMISSIONS_PAGE, "desktop-notification");
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function testDeny() {
|
||||
await BrowserTestUtils.withNewTab(PERMISSIONS_PAGE, async function(browser) {
|
||||
await showPermissionPrompt(browser);
|
||||
|
||||
checkEventTelemetry("show");
|
||||
|
||||
let notification = PopupNotifications.panel.firstElementChild;
|
||||
EventUtils.synthesizeMouseAtCenter(notification.secondaryButton, {});
|
||||
|
||||
checkEventTelemetry("deny");
|
||||
|
||||
Services.telemetry.clearEvents();
|
||||
PermissionTestUtils.remove(PERMISSIONS_PAGE, "desktop-notification");
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function testLeave() {
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(
|
||||
gBrowser,
|
||||
PERMISSIONS_PAGE
|
||||
);
|
||||
await showPermissionPrompt(tab.linkedBrowser);
|
||||
|
||||
checkEventTelemetry("show");
|
||||
|
||||
let tabClosed = BrowserTestUtils.waitForTabClosing(tab);
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
await tabClosed;
|
||||
|
||||
checkEventTelemetry("leave");
|
||||
|
||||
Services.telemetry.clearEvents();
|
||||
PermissionTestUtils.remove(PERMISSIONS_PAGE, "desktop-notification");
|
||||
});
|
@ -190,7 +190,6 @@ add_task(async function testChromeHearsPluginCrashFirst() {
|
||||
let event = new content.PluginCrashedEvent("PluginCrashed", {
|
||||
pluginName: "",
|
||||
pluginDumpID: "",
|
||||
browserDumpID: "",
|
||||
submittedCrashReport: false,
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
@ -247,7 +246,6 @@ add_task(async function testContentHearsCrashFirst() {
|
||||
let event = new content.PluginCrashedEvent("PluginCrashed", {
|
||||
pluginName: "",
|
||||
pluginDumpID: "",
|
||||
browserDumpID: "",
|
||||
submittedCrashReport: false,
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
|
@ -35,7 +35,7 @@ let whitelist = [
|
||||
isFromDevTools: false,
|
||||
},
|
||||
{
|
||||
sourceName: /\b(html|mathml|ua)\.css$/i,
|
||||
sourceName: /\b(minimal-xul|html|mathml|ua)\.css$/i,
|
||||
errorMessage: /Unknown property.*-moz-/i,
|
||||
isFromDevTools: false,
|
||||
},
|
||||
@ -57,7 +57,7 @@ let whitelist = [
|
||||
platforms: ["linux"],
|
||||
isFromDevTools: false,
|
||||
},
|
||||
// The '-moz-menulist-button' value is only supported in chrome and UA sheets
|
||||
// The '-moz-menulist-arrow-button' value is only supported in chrome and UA sheets
|
||||
// but forms.css is loaded as a document sheet by this test.
|
||||
// Maybe bug 1261237 will fix this?
|
||||
{
|
||||
@ -101,19 +101,6 @@ if (
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
!Services.prefs.getBoolPref(
|
||||
"layout.css.line-height-moz-block-height.content.enabled"
|
||||
)
|
||||
) {
|
||||
// -moz-block-height is used in form controls but not exposed to the web.
|
||||
whitelist.push({
|
||||
sourceName: /(?:res|gre-resources)\/forms\.css$/i,
|
||||
errorMessage: /Error in parsing value for \u2018line-height\u2019/iu,
|
||||
isFromDevTools: false,
|
||||
});
|
||||
}
|
||||
|
||||
if (!Services.prefs.getBoolPref("layout.css.scrollbar-width.enabled")) {
|
||||
whitelist.push({
|
||||
sourceName: /(?:res|gre-resources)\/forms\.css$/i,
|
||||
@ -122,6 +109,15 @@ if (!Services.prefs.getBoolPref("layout.css.scrollbar-width.enabled")) {
|
||||
});
|
||||
}
|
||||
|
||||
if (!Services.prefs.getBoolPref("layout.css.file-chooser-button.enabled")) {
|
||||
// Reserved to UA sheets, behind a pref for content.
|
||||
whitelist.push({
|
||||
sourceName: /(?:res|gre-resources)\/forms\.css$/i,
|
||||
errorMessage: /Unknown pseudo-.*file-chooser-button/i,
|
||||
isFromDevTools: false,
|
||||
});
|
||||
}
|
||||
|
||||
if (!Services.prefs.getBoolPref("layout.css.scroll-anchoring.enabled")) {
|
||||
whitelist.push({
|
||||
sourceName: /webconsole\.css$/i,
|
||||
|
@ -1,4 +1,5 @@
|
||||
const PREF_MULTISELECT_TABS = "browser.tabs.multiselect";
|
||||
const PREF_DELAY_AUTOPLAY = "media.block-autoplay-until-in-foreground";
|
||||
const PAGE =
|
||||
"https://example.com/browser/browser/base/content/test/tabs/file_mediaPlayback.html";
|
||||
|
||||
@ -19,7 +20,7 @@ async function addMediaTab() {
|
||||
|
||||
add_task(async function setPref() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [[PREF_MULTISELECT_TABS, true]],
|
||||
set: [[PREF_MULTISELECT_TABS, true], [PREF_DELAY_AUTOPLAY, true]],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1090,7 +1090,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
} else {
|
||||
// Only copy exposable URIs
|
||||
try {
|
||||
aURI = Services.uriFixup.createExposableURI(aURI);
|
||||
aURI = Services.io.createExposableURI(aURI);
|
||||
} catch (ex) {}
|
||||
}
|
||||
return aURI;
|
||||
|
@ -1028,10 +1028,6 @@ BrowserGlue.prototype = {
|
||||
os.removeObserver(this, "xpi-signature-changed");
|
||||
os.removeObserver(this, "sync-ui-state:update");
|
||||
|
||||
Services.prefs.removeObserver(
|
||||
"permissions.eventTelemetry.enabled",
|
||||
this._togglePermissionPromptTelemetry
|
||||
);
|
||||
Services.prefs.removeObserver(
|
||||
"privacy.trackingprotection",
|
||||
this._matchCBCategory
|
||||
@ -1590,24 +1586,6 @@ BrowserGlue.prototype = {
|
||||
ContentBlockingCategoriesPrefs.updateCBCategory();
|
||||
},
|
||||
|
||||
_togglePermissionPromptTelemetry() {
|
||||
let enablePermissionPromptTelemetry = Services.prefs.getBoolPref(
|
||||
"permissions.eventTelemetry.enabled",
|
||||
false
|
||||
);
|
||||
|
||||
Services.telemetry.setEventRecordingEnabled(
|
||||
"security.ui.permissionprompt",
|
||||
enablePermissionPromptTelemetry
|
||||
);
|
||||
|
||||
if (!enablePermissionPromptTelemetry) {
|
||||
// Remove the saved unique identifier to reduce the (remote) chance
|
||||
// of leaking it to our servers in the future.
|
||||
Services.prefs.clearUserPref("permissions.eventTelemetry.uuid");
|
||||
}
|
||||
},
|
||||
|
||||
_recordContentBlockingTelemetry() {
|
||||
let recordIdentityPopupEvents = Services.prefs.getBoolPref(
|
||||
"security.identitypopup.recordEventElemetry"
|
||||
@ -1840,14 +1818,6 @@ BrowserGlue.prototype = {
|
||||
);
|
||||
});
|
||||
|
||||
Services.tm.idleDispatchToMainThread(() => {
|
||||
Services.prefs.addObserver(
|
||||
"permissions.eventTelemetry.enabled",
|
||||
this._togglePermissionPromptTelemetry
|
||||
);
|
||||
this._togglePermissionPromptTelemetry();
|
||||
});
|
||||
|
||||
Services.tm.idleDispatchToMainThread(() => {
|
||||
this._recordContentBlockingTelemetry();
|
||||
});
|
||||
|
@ -1806,8 +1806,8 @@ var PanelView = class extends AssociatedToNode {
|
||||
focusSelectedElement(byKey = false) {
|
||||
let selected = this.selectedElement;
|
||||
if (selected) {
|
||||
let flag = byKey ? "FLAG_BYKEY" : "FLAG_BYELEMENTFOCUS";
|
||||
Services.focus.setFocus(selected, Services.focus[flag]);
|
||||
let flag = byKey ? Services.focus.FLAG_BYKEY : 0;
|
||||
Services.focus.setFocus(selected, flag);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,11 @@ function simulateItemDragAndEnd(aToDrag, aTarget) {
|
||||
Ci.nsIDragService
|
||||
);
|
||||
|
||||
ds.startDragSession();
|
||||
ds.startDragSessionForTests(
|
||||
Ci.nsIDragService.DRAGDROP_ACTION_MOVE |
|
||||
Ci.nsIDragService.DRAGDROP_ACTION_COPY |
|
||||
Ci.nsIDragService.DRAGDROP_ACTION_LINK
|
||||
);
|
||||
try {
|
||||
var [result, dataTransfer] = EventUtils.synthesizeDragOver(
|
||||
aToDrag.parentNode,
|
||||
|
@ -39,7 +39,11 @@ add_task(async function() {
|
||||
Ci.nsIDragService
|
||||
);
|
||||
|
||||
ds.startDragSession();
|
||||
ds.startDragSessionForTests(
|
||||
Ci.nsIDragService.DRAGDROP_ACTION_MOVE |
|
||||
Ci.nsIDragService.DRAGDROP_ACTION_COPY |
|
||||
Ci.nsIDragService.DRAGDROP_ACTION_LINK
|
||||
);
|
||||
try {
|
||||
var [result, dataTransfer] = EventUtils.synthesizeDragOver(
|
||||
identityBox,
|
||||
|
@ -10,7 +10,7 @@ The Activity Stream system add-on sends various types of pings to the backend (H
|
||||
|
||||
Schema definitions/validations that can be used for tests can be found in `system-addon/test/schemas/pings.js`.
|
||||
|
||||
# Example Activity Stream `health` log
|
||||
## Example Activity Stream `health` log
|
||||
|
||||
```js
|
||||
{
|
||||
@ -30,7 +30,7 @@ Schema definitions/validations that can be used for tests can be found in `syste
|
||||
}
|
||||
```
|
||||
|
||||
# Example Activity Stream `session` Log
|
||||
## Example Activity Stream `session` Log
|
||||
|
||||
```js
|
||||
{
|
||||
@ -54,7 +54,7 @@ Schema definitions/validations that can be used for tests can be found in `syste
|
||||
}
|
||||
```
|
||||
|
||||
# Example Activity Stream `user_event` Log
|
||||
## Example Activity Stream `user_event` Log
|
||||
|
||||
```js
|
||||
{
|
||||
@ -79,7 +79,7 @@ Schema definitions/validations that can be used for tests can be found in `syste
|
||||
}
|
||||
```
|
||||
|
||||
# Example Activity Stream `performance` Log
|
||||
## Example Activity Stream `performance` Log
|
||||
|
||||
```js
|
||||
{
|
||||
@ -103,7 +103,7 @@ Schema definitions/validations that can be used for tests can be found in `syste
|
||||
}
|
||||
```
|
||||
|
||||
# Example Activity Stream `undesired event` Log
|
||||
## Example Activity Stream `undesired event` Log
|
||||
|
||||
```js
|
||||
{
|
||||
@ -124,7 +124,7 @@ Schema definitions/validations that can be used for tests can be found in `syste
|
||||
"date": "2016-03-07"
|
||||
}
|
||||
```
|
||||
# Example Activity Stream `impression_stats` Logs
|
||||
## Example Activity Stream `impression_stats` Logs
|
||||
|
||||
```js
|
||||
{
|
||||
@ -162,7 +162,7 @@ Schema definitions/validations that can be used for tests can be found in `syste
|
||||
}
|
||||
```
|
||||
|
||||
# Example Discovery Stream `SPOCS Fill` log
|
||||
## Example Discovery Stream `SPOCS Fill` log
|
||||
|
||||
```js
|
||||
{
|
||||
@ -186,7 +186,7 @@ Schema definitions/validations that can be used for tests can be found in `syste
|
||||
}
|
||||
```
|
||||
|
||||
# Example Activity Stream `Router` Pings
|
||||
## Example Activity Stream `Router` Pings
|
||||
|
||||
```js
|
||||
{
|
||||
|
@ -362,7 +362,6 @@ PlacesController.prototype = {
|
||||
var clipboard = this.clipboard;
|
||||
var hasPlacesData = clipboard.hasDataMatchingFlavors(
|
||||
flavors,
|
||||
flavors.length,
|
||||
Ci.nsIClipboard.kGlobalClipboard
|
||||
);
|
||||
if (hasPlacesData) {
|
||||
|
@ -5,7 +5,7 @@
|
||||
for var in ('MOZ_APP_NAME', 'MOZ_MACBUNDLE_NAME'):
|
||||
DEFINES[var] = CONFIG[var]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk3', 'cocoa'):
|
||||
DEFINES['HAVE_SHELL_SERVICE'] = 1
|
||||
#if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk3', 'cocoa'):
|
||||
# DEFINES['HAVE_SHELL_SERVICE'] = 1
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
|
@ -14,8 +14,8 @@ BROWSER_CHROME_MANIFESTS += [
|
||||
for var in ('MOZ_APP_NAME', 'MOZ_MACBUNDLE_NAME'):
|
||||
DEFINES[var] = CONFIG[var]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk3', 'cocoa'):
|
||||
DEFINES['HAVE_SHELL_SERVICE'] = 1
|
||||
#if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk3', 'cocoa'):
|
||||
# DEFINES['HAVE_SHELL_SERVICE'] = 1
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
|
||||
|
@ -18,23 +18,27 @@ add_task(async function test() {
|
||||
let privateWin = await BrowserTestUtils.openNewBrowserWindow({
|
||||
private: true,
|
||||
});
|
||||
let privateBrowser = BrowserTestUtils.addTab(
|
||||
privateWin.gBrowser,
|
||||
prefix + "browser_privatebrowsing_localStorage_before_after_page.html"
|
||||
).linkedBrowser;
|
||||
await BrowserTestUtils.browserLoaded(privateBrowser);
|
||||
let testURL =
|
||||
prefix + "browser_privatebrowsing_localStorage_before_after_page.html";
|
||||
await BrowserTestUtils.openNewForegroundTab(privateWin.gBrowser, testURL);
|
||||
|
||||
is(privateBrowser.contentTitle, "1", "localStorage should contain 1 item");
|
||||
is(
|
||||
privateWin.gBrowser.selectedBrowser.contentTitle,
|
||||
"1",
|
||||
"localStorage should contain 1 item"
|
||||
);
|
||||
|
||||
// Step 2.
|
||||
let win = await BrowserTestUtils.openNewBrowserWindow();
|
||||
let browser = BrowserTestUtils.addTab(
|
||||
win.gBrowser,
|
||||
prefix + "browser_privatebrowsing_localStorage_before_after_page2.html"
|
||||
).linkedBrowser;
|
||||
await BrowserTestUtils.browserLoaded(browser);
|
||||
testURL =
|
||||
prefix + "browser_privatebrowsing_localStorage_before_after_page2.html";
|
||||
await BrowserTestUtils.openNewForegroundTab(win.gBrowser, testURL);
|
||||
|
||||
is(browser.contentTitle, "null|0", "localStorage should contain 0 items");
|
||||
is(
|
||||
win.gBrowser.selectedBrowser.contentTitle,
|
||||
"null|0",
|
||||
"localStorage should contain 0 items"
|
||||
);
|
||||
|
||||
// Cleanup
|
||||
await BrowserTestUtils.closeWindow(privateWin);
|
||||
|
@ -5,10 +5,6 @@
|
||||
* Ensure that we can restore old style favicon and principals.
|
||||
*/
|
||||
add_task(async function test_label_and_icon() {
|
||||
let helper = Cc["@mozilla.org/network/serialization-helper;1"].getService(
|
||||
Ci.nsISerializationHelper
|
||||
);
|
||||
|
||||
// Make sure that tabs are restored on demand as otherwise the tab will start
|
||||
// loading immediately and override the icon.
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
@ -24,7 +20,7 @@ add_task(async function test_label_and_icon() {
|
||||
await promiseBrowserLoaded(browser);
|
||||
|
||||
let contentPrincipal = browser.contentPrincipal;
|
||||
let serializedPrincipal = helper.serializeToString(contentPrincipal);
|
||||
let serializedPrincipal = E10SUtils.serializePrincipal(contentPrincipal);
|
||||
|
||||
// Retrieve the tab state.
|
||||
await TabStateFlusher.flush(browser);
|
||||
|
@ -48,9 +48,13 @@ if (sessionHistory) {
|
||||
* to modify and query docShell data when running with multiple processes.
|
||||
*/
|
||||
|
||||
addEventListener("hashchange", function() {
|
||||
sendAsyncMessage("ss-test:hashchange");
|
||||
});
|
||||
addEventListener(
|
||||
"hashchange",
|
||||
function() {
|
||||
sendAsyncMessage("ss-test:hashchange");
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
addMessageListener("ss-test:getStyleSheets", function(msg) {
|
||||
let sheets = content.document.styleSheets;
|
||||
|
@ -148,9 +148,7 @@ nsMacShellService::SetDesktopBackground(Element* aElement, int32_t aPosition,
|
||||
loadContext = do_QueryInterface(docShell);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIReferrerInfo> referrerInfo = new mozilla::dom::ReferrerInfo();
|
||||
referrerInfo->InitWithNode(aElement);
|
||||
|
||||
auto referrerInfo = mozilla::MakeRefPtr<mozilla::dom::ReferrerInfo>(*aElement);
|
||||
return wbp->SaveURI(imageURI, aElement->NodePrincipal(), 0, referrerInfo,
|
||||
nullptr, nullptr, mBackgroundFile, loadContext);
|
||||
}
|
||||
|
@ -210,8 +210,8 @@ class UrlbarInput {
|
||||
this._compositionState = UrlbarUtils.COMPOSITION.NONE;
|
||||
this._compositionClosedPopup = false;
|
||||
|
||||
this.editor.QueryInterface(Ci.nsIPlaintextEditor).newlineHandling =
|
||||
Ci.nsIPlaintextEditor.eNewlinesStripSurroundingWhitespace;
|
||||
this.editor.newlineHandling =
|
||||
Ci.nsIEditor.eNewlinesStripSurroundingWhitespace;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -328,7 +328,7 @@ class UrlbarInput {
|
||||
}
|
||||
|
||||
try {
|
||||
return Services.uriFixup.createExposableURI(uri);
|
||||
return Services.io.createExposableURI(uri);
|
||||
} catch (ex) {}
|
||||
|
||||
return uri;
|
||||
@ -1567,9 +1567,8 @@ class UrlbarInput {
|
||||
}
|
||||
|
||||
_on_overflow(event) {
|
||||
const targetIsPlaceholder = !event.originalTarget.classList.contains(
|
||||
"anonymous-div"
|
||||
);
|
||||
const targetIsPlaceholder =
|
||||
event.originalTarget.implementedPseudoElement == "::placeholder";
|
||||
// We only care about the non-placeholder text.
|
||||
// This shouldn't be needed, see bug 1487036.
|
||||
if (targetIsPlaceholder) {
|
||||
@ -1580,9 +1579,8 @@ class UrlbarInput {
|
||||
}
|
||||
|
||||
_on_underflow(event) {
|
||||
const targetIsPlaceholder = !event.originalTarget.classList.contains(
|
||||
"anonymous-div"
|
||||
);
|
||||
const targetIsPlaceholder =
|
||||
event.originalTarget.implementedPseudoElement == "::placeholder";
|
||||
// We only care about the non-placeholder text.
|
||||
// This shouldn't be needed, see bug 1487036.
|
||||
if (targetIsPlaceholder) {
|
||||
|
@ -115,9 +115,6 @@ class ProviderUnifiedComplete extends UrlbarProvider {
|
||||
// This is necessary because we insert matches one by one, thus we don't
|
||||
// want UnifiedComplete to reuse results.
|
||||
params.push(`insert-method:${UrlbarUtils.INSERTMETHOD.APPEND}`);
|
||||
// The Quantum Bar has its own telemetry measurement, thus disable old
|
||||
// telemetry logged by UnifiedComplete.
|
||||
params.push("disable-telemetry");
|
||||
if (queryContext.isPrivate) {
|
||||
params.push("private-window");
|
||||
if (!PrivateBrowsingUtils.permanentPrivateBrowsing) {
|
||||
@ -285,10 +282,7 @@ function makeUrlbarResult(tokens, info) {
|
||||
if (!title) {
|
||||
// If the url doesn't have an host (e.g. javascript urls), comment
|
||||
// will be empty, and we can't build the usual title. Thus use the url.
|
||||
title = Services.textToSubURI.unEscapeURIForUI(
|
||||
"UTF-8",
|
||||
action.params.url
|
||||
);
|
||||
title = Services.textToSubURI.unEscapeURIForUI(action.params.url);
|
||||
} else if (tokens && tokens.length > 1) {
|
||||
title = bundle.formatStringFromName(
|
||||
"bookmarkKeywordSearch",
|
||||
|
@ -184,10 +184,7 @@ class UrlbarResult {
|
||||
if (UrlbarPrefs.get("trimURLs")) {
|
||||
url = BrowserUtils.trimURL(url || "");
|
||||
}
|
||||
payloadInfo.displayUrl[0] = Services.textToSubURI.unEscapeURIForUI(
|
||||
"UTF-8",
|
||||
url
|
||||
);
|
||||
payloadInfo.displayUrl[0] = Services.textToSubURI.unEscapeURIForUI(url);
|
||||
}
|
||||
|
||||
// For performance reasons limit excessive string lengths, to reduce the
|
||||
|
@ -17,7 +17,7 @@ add_task(async function test_ignoreFragment() {
|
||||
tabRefAboutHome.linkedBrowser,
|
||||
null,
|
||||
async function() {
|
||||
await ContentTaskUtils.waitForEvent(this, "hashchange", false);
|
||||
await ContentTaskUtils.waitForEvent(this, "hashchange", true);
|
||||
}
|
||||
);
|
||||
switchTab("about:home#2", true, {
|
||||
|
@ -1 +1 @@
|
||||
68.13.8
|
||||
68.13.9
|
||||
|
@ -1 +1 @@
|
||||
68.13.8b
|
||||
68.13.9b
|
||||
|
@ -76,11 +76,6 @@ ChromeUtils.defineModuleGetter(
|
||||
"PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"PermissionUITelemetry",
|
||||
"resource:///modules/PermissionUITelemetry.jsm"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(
|
||||
this,
|
||||
@ -170,17 +165,6 @@ var PermissionPromptPrototype = {
|
||||
return undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
* A string that needs to be set to include this prompt in
|
||||
* experimental event telemetry collection.
|
||||
*
|
||||
* This needs to conform to event telemetry string rules,
|
||||
* i.e. it needs to be an alphabetic string under 20 characters.
|
||||
*/
|
||||
get permissionTelemetryKey() {
|
||||
return undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
* If true, user permissions will be read from and written to.
|
||||
* When this is false, we still provide integration with
|
||||
@ -445,8 +429,6 @@ var PermissionPromptPrototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
this._buttonAction = null;
|
||||
|
||||
// Transform the PermissionPrompt actions into PopupNotification actions.
|
||||
let popupNotificationActions = [];
|
||||
for (let promptAction of this.promptActions) {
|
||||
@ -489,16 +471,9 @@ var PermissionPromptPrototype = {
|
||||
}
|
||||
|
||||
// Grant permission if action is ALLOW.
|
||||
// Record buttonAction for telemetry.
|
||||
if (promptAction.action == SitePermissions.ALLOW) {
|
||||
this._buttonAction = "accept";
|
||||
this.allow();
|
||||
} else {
|
||||
if (promptAction.scope == SitePermissions.SCOPE_PERSISTENT) {
|
||||
this._buttonAction = "never";
|
||||
} else {
|
||||
this._buttonAction = "deny";
|
||||
}
|
||||
this.cancel();
|
||||
}
|
||||
} else if (this.permissionKey) {
|
||||
@ -596,20 +571,6 @@ var PermissionPromptPrototype = {
|
||||
|
||||
let options = this.popupOptions;
|
||||
|
||||
let telemetryData = null;
|
||||
if (this.request && this.permissionTelemetryKey) {
|
||||
telemetryData = {
|
||||
permissionTelemetryKey: this.permissionTelemetryKey,
|
||||
permissionKey: this.permissionKey,
|
||||
principal: this.principal,
|
||||
documentDOMContentLoadedTimestamp: this.request
|
||||
.documentDOMContentLoadedTimestamp,
|
||||
isHandlingUserInput: this.request.isHandlingUserInput,
|
||||
userHadInteractedWithDocument: this.request
|
||||
.userHadInteractedWithDocument,
|
||||
};
|
||||
}
|
||||
|
||||
if (!options.hasOwnProperty("displayURI") || options.displayURI) {
|
||||
options.displayURI = this.principal.URI;
|
||||
}
|
||||
@ -641,13 +602,6 @@ var PermissionPromptPrototype = {
|
||||
// You can remove this restriction if you need it, but be
|
||||
// mindful of other consumers.
|
||||
if (topic == "removed" && !postPrompt) {
|
||||
if (telemetryData) {
|
||||
PermissionUITelemetry.onRemoved(
|
||||
telemetryData,
|
||||
this._buttonAction,
|
||||
nextRemovalReason
|
||||
);
|
||||
}
|
||||
this.onAfterShow();
|
||||
}
|
||||
return false;
|
||||
@ -670,9 +624,6 @@ var PermissionPromptPrototype = {
|
||||
secondaryActions,
|
||||
options
|
||||
);
|
||||
if (telemetryData) {
|
||||
PermissionUITelemetry.onShow(telemetryData);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
@ -733,10 +684,6 @@ GeolocationPermissionPrompt.prototype = {
|
||||
return "geo";
|
||||
},
|
||||
|
||||
get permissionTelemetryKey() {
|
||||
return "geo";
|
||||
},
|
||||
|
||||
get popupOptions() {
|
||||
let pref = "browser.geolocation.warning.infoURL";
|
||||
let options = {
|
||||
@ -836,10 +783,6 @@ DesktopNotificationPermissionPrompt.prototype = {
|
||||
return "desktop-notification";
|
||||
},
|
||||
|
||||
get permissionTelemetryKey() {
|
||||
return "notifications";
|
||||
},
|
||||
|
||||
get popupOptions() {
|
||||
let learnMoreURL =
|
||||
Services.urlFormatter.formatURLPref("app.support.baseURL") + "push";
|
||||
@ -1120,7 +1063,7 @@ StorageAccessPermissionPrompt.prototype = {
|
||||
|
||||
prettifyHostPort(uri) {
|
||||
try {
|
||||
uri = Services.uriFixup.createExposableURI(uri);
|
||||
uri = Services.io.createExposableURI(uri);
|
||||
} catch (e) {
|
||||
// ignore, since we can't do anything better
|
||||
}
|
||||
|
@ -1,178 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["PermissionUITelemetry"];
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"Services",
|
||||
"resource://gre/modules/Services.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"CryptoUtils",
|
||||
"resource://services-crypto/utils.js"
|
||||
);
|
||||
|
||||
const TELEMETRY_STAT_REMOVAL_LEAVE_PAGE = 6;
|
||||
|
||||
var PermissionUITelemetry = {
|
||||
// Returns a hash of the host name in combination with a unique local user id.
|
||||
// This allows us to track duplicate prompts on sites while not revealing the user's
|
||||
// browsing history.
|
||||
_uniqueHostHash(host) {
|
||||
// Gets a unique user ID as salt, that needs to stay local to this profile and not be
|
||||
// sent to any server!
|
||||
let salt = Services.prefs.getStringPref(
|
||||
"permissions.eventTelemetry.salt",
|
||||
null
|
||||
);
|
||||
if (!salt) {
|
||||
salt = Cc["@mozilla.org/uuid-generator;1"]
|
||||
.getService(Ci.nsIUUIDGenerator)
|
||||
.generateUUID()
|
||||
.toString();
|
||||
Services.prefs.setStringPref("permissions.eventTelemetry.salt", salt);
|
||||
}
|
||||
|
||||
let domain;
|
||||
try {
|
||||
domain = Services.eTLD.getBaseDomainFromHost(host);
|
||||
} catch (e) {
|
||||
domain = host;
|
||||
}
|
||||
|
||||
return CryptoUtils.sha256(domain + salt);
|
||||
},
|
||||
|
||||
_previousVisitCount(host) {
|
||||
let historyService = Cc[
|
||||
"@mozilla.org/browser/nav-history-service;1"
|
||||
].getService(Ci.nsINavHistoryService);
|
||||
|
||||
let options = historyService.getNewQueryOptions();
|
||||
options.resultType = options.RESULTS_AS_VISIT;
|
||||
|
||||
// Search for visits to this host before today
|
||||
let query = historyService.getNewQuery();
|
||||
query.endTimeReference = query.TIME_RELATIVE_TODAY;
|
||||
query.endTime = 0;
|
||||
query.domain = host;
|
||||
|
||||
let result = historyService.executeQuery(query, options);
|
||||
result.root.containerOpen = true;
|
||||
let cc = result.root.childCount;
|
||||
result.root.containerOpen = false;
|
||||
return cc;
|
||||
},
|
||||
|
||||
_collectExtraKeys(prompt) {
|
||||
let lastInteraction = 0;
|
||||
// "storageAccessAPI" is the name of the permission that tells us whether the
|
||||
// user has interacted with a particular site in the first-party context before.
|
||||
let interactionPermission = Services.perms.getPermissionObject(
|
||||
prompt.principal,
|
||||
"storageAccessAPI",
|
||||
false
|
||||
);
|
||||
if (interactionPermission) {
|
||||
lastInteraction = interactionPermission.modificationTime;
|
||||
}
|
||||
|
||||
let allPermsDenied = 0;
|
||||
let allPermsGranted = 0;
|
||||
let thisPermDenied = 0;
|
||||
let thisPermGranted = 0;
|
||||
|
||||
let commonPermissions = [
|
||||
"geo",
|
||||
"desktop-notification",
|
||||
"camera",
|
||||
"microphone",
|
||||
"screen",
|
||||
];
|
||||
for (let perm of Services.perms.all) {
|
||||
if (!commonPermissions.includes(perm.type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (perm.capability == Services.perms.ALLOW_ACTION) {
|
||||
allPermsGranted++;
|
||||
if (perm.type == prompt.permissionKey) {
|
||||
thisPermGranted++;
|
||||
}
|
||||
}
|
||||
|
||||
if (perm.capability == Services.perms.DENY_ACTION) {
|
||||
allPermsDenied++;
|
||||
if (perm.type == prompt.permissionKey) {
|
||||
thisPermDenied++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let promptHost = prompt.principal.URI.host;
|
||||
|
||||
return {
|
||||
previousVisits: this._previousVisitCount(promptHost).toString(),
|
||||
timeOnPage: (
|
||||
Date.now() - prompt.documentDOMContentLoadedTimestamp
|
||||
).toString(),
|
||||
hasUserInput: prompt.isHandlingUserInput.toString(),
|
||||
docHasUserInput: prompt.userHadInteractedWithDocument.toString(),
|
||||
lastInteraction: lastInteraction.toString(),
|
||||
allPermsDenied: allPermsDenied.toString(),
|
||||
allPermsGranted: allPermsGranted.toString(),
|
||||
thisPermDenied: thisPermDenied.toString(),
|
||||
thisPermGranted: thisPermGranted.toString(),
|
||||
};
|
||||
},
|
||||
|
||||
onShow(prompt) {
|
||||
let object = prompt.permissionTelemetryKey;
|
||||
if (!object) {
|
||||
return;
|
||||
}
|
||||
|
||||
let extraKeys = this._collectExtraKeys(prompt);
|
||||
let hostHash = this._uniqueHostHash(prompt.principal.URI.host);
|
||||
Services.telemetry.recordEvent(
|
||||
"security.ui.permissionprompt",
|
||||
"show",
|
||||
object,
|
||||
hostHash,
|
||||
extraKeys
|
||||
);
|
||||
},
|
||||
|
||||
onRemoved(prompt, buttonAction, telemetryReason) {
|
||||
let object = prompt.permissionTelemetryKey;
|
||||
if (!object) {
|
||||
return;
|
||||
}
|
||||
|
||||
let method = "other";
|
||||
if (buttonAction == "accept") {
|
||||
method = "accept";
|
||||
} else if (buttonAction == "deny") {
|
||||
method = "deny";
|
||||
} else if (buttonAction == "never") {
|
||||
method = "never";
|
||||
} else if (telemetryReason == TELEMETRY_STAT_REMOVAL_LEAVE_PAGE) {
|
||||
method = "leave";
|
||||
}
|
||||
|
||||
let extraKeys = this._collectExtraKeys(prompt);
|
||||
let hostHash = this._uniqueHostHash(prompt.principal.URI.host);
|
||||
Services.telemetry.recordEvent(
|
||||
"security.ui.permissionprompt",
|
||||
method,
|
||||
object,
|
||||
hostHash,
|
||||
extraKeys
|
||||
);
|
||||
},
|
||||
};
|
@ -766,7 +766,7 @@ class PrincipalsCollector {
|
||||
async getAllPrincipalsInternal(progress) {
|
||||
progress.step = "principals-quota-manager";
|
||||
let principals = await new Promise(resolve => {
|
||||
quotaManagerService.listOrigins(request => {
|
||||
quotaManagerService.listOrigins().callback = request => {
|
||||
progress.step = "principals-quota-manager-listOrigins";
|
||||
if (request.resultCode != Cr.NS_OK) {
|
||||
// We are probably shutting down. We don't want to propagate the
|
||||
@ -776,9 +776,9 @@ class PrincipalsCollector {
|
||||
}
|
||||
|
||||
let list = [];
|
||||
for (let item of request.result) {
|
||||
for (const origin of request.result) {
|
||||
let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(
|
||||
item.origin
|
||||
origin
|
||||
);
|
||||
let uri = principal.URI;
|
||||
if (isSupportedURI(uri)) {
|
||||
@ -788,7 +788,7 @@ class PrincipalsCollector {
|
||||
|
||||
progress.step = "principals-quota-manager-completed";
|
||||
resolve(list);
|
||||
});
|
||||
};
|
||||
}).catch(ex => {
|
||||
Cu.reportError("QuotaManagerService promise failed: " + ex);
|
||||
return [];
|
||||
|
@ -77,9 +77,6 @@ with Files("OpenInTabsUtils.jsm"):
|
||||
with Files("PermissionUI.jsm"):
|
||||
BUG_COMPONENT = ("Firefox", "Site Identity and Permission Panels")
|
||||
|
||||
with Files("PermissionUITelemetry.jsm"):
|
||||
BUG_COMPONENT = ("Firefox", "Site Identity and Permission Panels")
|
||||
|
||||
with Files("ProcessHangMonitor.jsm"):
|
||||
BUG_COMPONENT = ("Core", "DOM: Content Processes")
|
||||
|
||||
@ -150,7 +147,6 @@ EXTRA_JS_MODULES += [
|
||||
'OpenInTabsUtils.jsm',
|
||||
'PageActions.jsm',
|
||||
'PermissionUI.jsm',
|
||||
'PermissionUITelemetry.jsm',
|
||||
'ProcessHangMonitor.jsm',
|
||||
'ReaderParent.jsm',
|
||||
'RemotePrompt.jsm',
|
||||
|
@ -87,9 +87,7 @@ function makeMockPermissionRequest(browser) {
|
||||
types.appendElement(type);
|
||||
let result = {
|
||||
types,
|
||||
documentDOMContentLoadedTimestamp: 0,
|
||||
isHandlingUserInput: false,
|
||||
userHadInteractedWithDocument: false,
|
||||
principal: browser.contentPrincipal,
|
||||
topLevelPrincipal: browser.contentPrincipal,
|
||||
requester: null,
|
||||
|
@ -31,6 +31,7 @@
|
||||
border: 1px solid @fieldBorderColor@;
|
||||
border-radius: var(--toolbarbutton-border-radius);
|
||||
box-shadow: 0 1px 4px rgba(0,0,0,.05);
|
||||
outline: none;
|
||||
padding: 0;
|
||||
margin: 3px 5px;
|
||||
min-height: 30px;
|
||||
|
@ -55,13 +55,11 @@
|
||||
void CanRunScriptChecker::registerMatchers(MatchFinder *AstMatcher) {
|
||||
auto Refcounted = qualType(hasDeclaration(cxxRecordDecl(isRefCounted())));
|
||||
auto StackSmartPtr =
|
||||
ignoreTrivials(
|
||||
declRefExpr(to(varDecl(hasAutomaticStorageDuration())),
|
||||
hasType(isSmartPtrToRefCounted())));
|
||||
ignoreTrivials(declRefExpr(to(varDecl(hasAutomaticStorageDuration(),
|
||||
hasType(isSmartPtrToRefCounted())))));
|
||||
auto ConstMemberOfThisSmartPtr =
|
||||
memberExpr(hasType(isSmartPtrToRefCounted()),
|
||||
hasType(isConstQualified()),
|
||||
hasObjectExpression(cxxThisExpr()));
|
||||
memberExpr(hasType(isSmartPtrToRefCounted()), hasType(isConstQualified()),
|
||||
hasObjectExpression(cxxThisExpr()));
|
||||
// A smartptr can be known-live for three reasons:
|
||||
// 1) It's declared on the stack.
|
||||
// 2) It's a const member of "this". We know "this" is alive (recursively)
|
||||
@ -70,15 +68,14 @@ void CanRunScriptChecker::registerMatchers(MatchFinder *AstMatcher) {
|
||||
// 3) It's an immediate temporary being constructed at the point where the
|
||||
// call is happening.
|
||||
auto KnownLiveSmartPtr = anyOf(
|
||||
StackSmartPtr,
|
||||
ConstMemberOfThisSmartPtr,
|
||||
ignoreTrivials(cxxConstructExpr(hasType(isSmartPtrToRefCounted()))));
|
||||
StackSmartPtr, ConstMemberOfThisSmartPtr,
|
||||
ignoreTrivials(cxxConstructExpr(hasType(isSmartPtrToRefCounted()))));
|
||||
|
||||
auto MozKnownLiveCall =
|
||||
ignoreTrivials(callExpr(callee(functionDecl(hasName("MOZ_KnownLive")))));
|
||||
ignoreTrivials(callExpr(callee(functionDecl(hasName("MOZ_KnownLive")))));
|
||||
|
||||
// Params of the calling function are presumed live, because it itself should be
|
||||
// MOZ_CAN_RUN_SCRIPT. Note that this is subject to
|
||||
// Params of the calling function are presumed live, because it itself should
|
||||
// be MOZ_CAN_RUN_SCRIPT. Note that this is subject to
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1537656 a the moment.
|
||||
auto KnownLiveParam = anyOf(
|
||||
// "this" is OK
|
||||
@ -108,15 +105,12 @@ void CanRunScriptChecker::registerMatchers(MatchFinder *AstMatcher) {
|
||||
// return non-live objects (e.g. consider "live_pointer->foo()" as an
|
||||
// example). For purposes of this analysis we are assuming the method
|
||||
// calls on smart ptrs all just return the pointer inside,
|
||||
cxxMemberCallExpr(on(
|
||||
allOf(hasType(isSmartPtrToRefCounted()),
|
||||
KnownLiveBase))),
|
||||
cxxMemberCallExpr(
|
||||
on(allOf(hasType(isSmartPtrToRefCounted()), KnownLiveBase))),
|
||||
// operator* or operator-> on a thing that is already known to be live.
|
||||
cxxOperatorCallExpr(
|
||||
anyOf(hasOverloadedOperatorName("*"),
|
||||
hasOverloadedOperatorName("->")),
|
||||
hasAnyArgument(KnownLiveBase),
|
||||
argumentCountIs(1)),
|
||||
cxxOperatorCallExpr(anyOf(hasOverloadedOperatorName("*"),
|
||||
hasOverloadedOperatorName("->")),
|
||||
hasAnyArgument(KnownLiveBase), argumentCountIs(1)),
|
||||
// A dereference on a thing that is known to be live. This is _not_
|
||||
// caught by the "operator* or operator->" clause above, because
|
||||
// cxxOperatorCallExpr() only catches cases when a class defines
|
||||
@ -139,47 +133,36 @@ void CanRunScriptChecker::registerMatchers(MatchFinder *AstMatcher) {
|
||||
// does not guarantee liveness; in fact the callee could modify those
|
||||
// things! In practice they would be the wrong type anyway, though, so
|
||||
// it's hard to add a test for this.
|
||||
unaryOperator(
|
||||
hasOperatorName("&"),
|
||||
hasUnaryOperand(allOf(
|
||||
anyOf(
|
||||
hasType(references(Refcounted)),
|
||||
hasType(Refcounted)),
|
||||
ignoreTrivials(KnownLiveBase))))
|
||||
);
|
||||
unaryOperator(hasOperatorName("&"),
|
||||
hasUnaryOperand(allOf(anyOf(hasType(references(Refcounted)),
|
||||
hasType(Refcounted)),
|
||||
ignoreTrivials(KnownLiveBase)))));
|
||||
|
||||
auto KnownLive = anyOf(
|
||||
// Anything above, of course.
|
||||
KnownLiveSimple,
|
||||
// Conditional operators where both arms are live.
|
||||
conditionalOperator(
|
||||
hasFalseExpression(ignoreTrivials(KnownLiveSimple)),
|
||||
hasTrueExpression(ignoreTrivials(KnownLiveSimple)))
|
||||
conditionalOperator(hasFalseExpression(ignoreTrivials(KnownLiveSimple)),
|
||||
hasTrueExpression(ignoreTrivials(KnownLiveSimple)))
|
||||
// We're not handling cases like a dereference of a conditional operator,
|
||||
// mostly because handling a dereference in general is so ugly. I
|
||||
// _really_ wish I could just write a recursive matcher here easily.
|
||||
);
|
||||
);
|
||||
|
||||
auto InvalidArg =
|
||||
ignoreTrivialsConditional(
|
||||
// We want to consider things if there is anything refcounted involved,
|
||||
// including in any of the trivials that we otherwise strip off.
|
||||
anyOf(
|
||||
hasType(Refcounted),
|
||||
hasType(pointsTo(Refcounted)),
|
||||
hasType(references(Refcounted)),
|
||||
hasType(isSmartPtrToRefCounted())
|
||||
),
|
||||
// We want to find any expression,
|
||||
expr(
|
||||
auto InvalidArg = ignoreTrivialsConditional(
|
||||
// We want to consider things if there is anything refcounted involved,
|
||||
// including in any of the trivials that we otherwise strip off.
|
||||
anyOf(hasType(Refcounted), hasType(pointsTo(Refcounted)),
|
||||
hasType(references(Refcounted)), hasType(isSmartPtrToRefCounted())),
|
||||
// We want to find any expression,
|
||||
expr(
|
||||
// which is not known live,
|
||||
unless(KnownLive),
|
||||
// and which is not a default arg with value nullptr, since those are
|
||||
// always safe,
|
||||
unless(cxxDefaultArgExpr(isNullDefaultArg())),
|
||||
// and which is not a literal nullptr,
|
||||
unless(cxxNullPtrLiteralExpr()),
|
||||
expr().bind("invalidArg")));
|
||||
unless(cxxNullPtrLiteralExpr()), expr().bind("invalidArg")));
|
||||
|
||||
// A matcher which will mark the first invalid argument it finds invalid, but
|
||||
// will always match, even if it finds no invalid arguments, so it doesn't
|
||||
@ -203,11 +186,7 @@ void CanRunScriptChecker::registerMatchers(MatchFinder *AstMatcher) {
|
||||
// which optionally has an invalid arg,
|
||||
OptionalInvalidExplicitArg,
|
||||
// or which optionally has an invalid this argument,
|
||||
anyOf(
|
||||
on(InvalidArg),
|
||||
anything()
|
||||
),
|
||||
expr().bind("callExpr")),
|
||||
anyOf(on(InvalidArg), anything()), expr().bind("callExpr")),
|
||||
// or a regular call expression,
|
||||
callExpr(
|
||||
// which optionally has an invalid arg.
|
||||
@ -238,10 +217,9 @@ namespace {
|
||||
/// any) also have the annotation.
|
||||
class FuncSetCallback : public MatchFinder::MatchCallback {
|
||||
public:
|
||||
FuncSetCallback(CanRunScriptChecker& Checker,
|
||||
FuncSetCallback(CanRunScriptChecker &Checker,
|
||||
std::unordered_set<const FunctionDecl *> &FuncSet)
|
||||
: CanRunScriptFuncs(FuncSet),
|
||||
Checker(Checker) {}
|
||||
: CanRunScriptFuncs(FuncSet), Checker(Checker) {}
|
||||
|
||||
void run(const MatchFinder::MatchResult &Result) override;
|
||||
|
||||
@ -277,14 +255,13 @@ void FuncSetCallback::checkOverriddenMethods(const CXXMethodDecl *Method) {
|
||||
const char *ErrorNonCanRunScriptOverridden =
|
||||
"functions marked as MOZ_CAN_RUN_SCRIPT cannot override functions "
|
||||
"that are not marked MOZ_CAN_RUN_SCRIPT";
|
||||
const char* NoteNonCanRunScriptOverridden =
|
||||
const char *NoteNonCanRunScriptOverridden =
|
||||
"overridden function declared here";
|
||||
|
||||
Checker.diag(Method->getLocation(), ErrorNonCanRunScriptOverridden,
|
||||
DiagnosticIDs::Error);
|
||||
Checker.diag(OverriddenMethod->getLocation(),
|
||||
NoteNonCanRunScriptOverridden,
|
||||
DiagnosticIDs::Note);
|
||||
NoteNonCanRunScriptOverridden, DiagnosticIDs::Note);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -300,9 +277,7 @@ void CanRunScriptChecker::buildFuncSet(ASTContext *Context) {
|
||||
Finder.addMatcher(
|
||||
functionDecl(hasCanRunScriptAnnotation()).bind("canRunScriptFunction"),
|
||||
&Callback);
|
||||
Finder.addMatcher(
|
||||
lambdaExpr().bind("lambda"),
|
||||
&Callback);
|
||||
Finder.addMatcher(lambdaExpr().bind("lambda"), &Callback);
|
||||
// We start the analysis, given the ASTContext our main checker is in.
|
||||
Finder.matchAST(*Context);
|
||||
}
|
||||
@ -327,7 +302,7 @@ void CanRunScriptChecker::check(const MatchFinder::MatchResult &Result) {
|
||||
const char *NoteNonCanRunScriptParent = "caller function declared here";
|
||||
|
||||
const Expr *InvalidArg;
|
||||
if (const CXXDefaultArgExpr* defaultArg =
|
||||
if (const CXXDefaultArgExpr *defaultArg =
|
||||
Result.Nodes.getNodeAs<CXXDefaultArgExpr>("invalidArg")) {
|
||||
InvalidArg = defaultArg->getExpr();
|
||||
} else {
|
||||
@ -383,11 +358,9 @@ void CanRunScriptChecker::check(const MatchFinder::MatchResult &Result) {
|
||||
// If we have an invalid argument in the call, we emit the diagnostic to
|
||||
// signal it.
|
||||
if (InvalidArg) {
|
||||
const std::string invalidArgText =
|
||||
Lexer::getSourceText(
|
||||
CharSourceRange::getTokenRange(InvalidArg->getSourceRange()),
|
||||
Result.Context->getSourceManager(),
|
||||
Result.Context->getLangOpts());
|
||||
const std::string invalidArgText = Lexer::getSourceText(
|
||||
CharSourceRange::getTokenRange(InvalidArg->getSourceRange()),
|
||||
Result.Context->getSourceManager(), Result.Context->getLangOpts());
|
||||
diag(InvalidArg->getExprLoc(), ErrorInvalidArg, DiagnosticIDs::Error)
|
||||
<< InvalidArg->getSourceRange() << invalidArgText;
|
||||
}
|
||||
|
@ -2,10 +2,10 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <algorithm>
|
||||
#include "CustomAttributes.h"
|
||||
#include "plugin.h"
|
||||
#include "clang/Frontend/FrontendPluginRegistry.h"
|
||||
#include <algorithm>
|
||||
|
||||
/* Having annotations in the AST unexpectedly impacts codegen.
|
||||
* Ideally, we'd avoid having annotations at all, by using an API such as
|
||||
@ -26,37 +26,34 @@
|
||||
using namespace clang;
|
||||
using namespace llvm;
|
||||
|
||||
static DenseMap<const Decl*, CustomAttributesSet> AttributesCache;
|
||||
static DenseMap<const Decl *, CustomAttributesSet> AttributesCache;
|
||||
|
||||
static CustomAttributesSet CacheAttributes(const Decl* D)
|
||||
{
|
||||
static CustomAttributesSet CacheAttributes(const Decl *D) {
|
||||
CustomAttributesSet attrs = {};
|
||||
for (auto Attr : D->specific_attrs<AnnotateAttr>()) {
|
||||
auto annotation = Attr->getAnnotation();
|
||||
#define ATTR(a) \
|
||||
if (annotation == #a) { \
|
||||
attrs.has_ ## a = true; \
|
||||
} else
|
||||
#define ATTR(a) \
|
||||
if (annotation == #a) { \
|
||||
attrs.has_##a = true; \
|
||||
} else
|
||||
#include "CustomAttributes.inc"
|
||||
#undef ATTR
|
||||
{}
|
||||
}
|
||||
const_cast<Decl*>(D)->dropAttr<AnnotateAttr>();
|
||||
const_cast<Decl *>(D)->dropAttr<AnnotateAttr>();
|
||||
AttributesCache.insert(std::make_pair(D, attrs));
|
||||
return attrs;
|
||||
}
|
||||
|
||||
static void Report(const Decl* D, const char* message)
|
||||
{
|
||||
ASTContext& Context = D->getASTContext();
|
||||
DiagnosticsEngine& Diag = Context.getDiagnostics();
|
||||
unsigned ID = Diag.getDiagnosticIDs()->getCustomDiagID(
|
||||
DiagnosticIDs::Warning, message);
|
||||
static void Report(const Decl *D, const char *message) {
|
||||
ASTContext &Context = D->getASTContext();
|
||||
DiagnosticsEngine &Diag = Context.getDiagnostics();
|
||||
unsigned ID =
|
||||
Diag.getDiagnosticIDs()->getCustomDiagID(DiagnosticIDs::Warning, message);
|
||||
Diag.Report(D->getBeginLoc(), ID);
|
||||
}
|
||||
|
||||
CustomAttributesSet GetAttributes(const Decl* D)
|
||||
{
|
||||
CustomAttributesSet GetAttributes(const Decl *D) {
|
||||
CustomAttributesSet attrs = {};
|
||||
if (D->hasAttr<AnnotateAttr>()) {
|
||||
Report(D, "Declaration has unhandled annotations.");
|
||||
@ -70,22 +67,22 @@ CustomAttributesSet GetAttributes(const Decl* D)
|
||||
return attrs;
|
||||
}
|
||||
|
||||
bool hasCustomAttribute(const clang::Decl* D, CustomAttributes A)
|
||||
{
|
||||
bool hasCustomAttribute(const clang::Decl *D, CustomAttributes A) {
|
||||
CustomAttributesSet attrs = GetAttributes(D);
|
||||
switch (A) {
|
||||
#define ATTR(a) case a: return attrs.has_ ## a;
|
||||
#define ATTR(a) \
|
||||
case a: \
|
||||
return attrs.has_##a;
|
||||
#include "CustomAttributes.inc"
|
||||
#undef ATTR
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class CustomAttributesMatcher : public ast_matchers::MatchFinder::MatchCallback {
|
||||
class CustomAttributesMatcher
|
||||
: public ast_matchers::MatchFinder::MatchCallback {
|
||||
public:
|
||||
virtual void
|
||||
run(const ast_matchers::MatchFinder::MatchResult &Result) final
|
||||
{
|
||||
void run(const ast_matchers::MatchFinder::MatchResult &Result) final {
|
||||
if (auto D = Result.Nodes.getNodeAs<Decl>("decl")) {
|
||||
CacheAttributes(D);
|
||||
} else if (auto L = Result.Nodes.getNodeAs<LambdaExpr>("lambda")) {
|
||||
@ -99,9 +96,10 @@ class CustomAttributesAction : public PluginASTAction {
|
||||
public:
|
||||
ASTConsumerPtr CreateASTConsumer(CompilerInstance &CI,
|
||||
StringRef FileName) override {
|
||||
auto& Context = CI.getASTContext();
|
||||
auto &Context = CI.getASTContext();
|
||||
auto AstMatcher = new (Context.Allocate<MatchFinder>()) MatchFinder();
|
||||
auto Matcher = new (Context.Allocate<CustomAttributesMatcher>()) CustomAttributesMatcher();
|
||||
auto Matcher = new (Context.Allocate<CustomAttributesMatcher>())
|
||||
CustomAttributesMatcher();
|
||||
AstMatcher->addMatcher(decl().bind("decl"), Matcher);
|
||||
AstMatcher->addMatcher(lambdaExpr().bind("lambda"), Matcher);
|
||||
return AstMatcher->newASTConsumer();
|
||||
@ -112,11 +110,8 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
ActionType getActionType() override {
|
||||
return AddBeforeMainAction;
|
||||
}
|
||||
ActionType getActionType() override { return AddBeforeMainAction; }
|
||||
};
|
||||
|
||||
static FrontendPluginRegistry::Add<CustomAttributesAction> X(
|
||||
"moz-custom-attributes",
|
||||
"prepare custom attributes for moz-check");
|
||||
static FrontendPluginRegistry::Add<CustomAttributesAction>
|
||||
X("moz-custom-attributes", "prepare custom attributes for moz-check");
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user