Bug 1695435 - Part 2: Add more words to the chrome script heuristic in use-isInstance r=preferences-reviewers,Gijs,webdriver-reviewers,whimboo,sgalich

Differential Revision: https://phabricator.services.mozilla.com/D110932
This commit is contained in:
Kagami Sascha Rosylight 2022-08-24 22:47:42 +00:00
parent ecf7215279
commit 102bd338be
27 changed files with 78 additions and 60 deletions

View file

@ -26,7 +26,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=429547
// gA11yEventDumpToConsole = true; // debugging
function changeARIAActiveDescendant(aContainer, aItem, aPrevItemId) {
let itemID = aItem instanceof Node ? aItem.id : aItem;
let itemID = Node.isInstance(aItem) ? aItem.id : aItem;
this.eventSeq = [new focusChecker(aItem)];
if (aPrevItemId) {

View file

@ -501,7 +501,7 @@ var gGestureSupport = {
* The MozRotateGestureUpdate event triggering this call
*/
rotate(aEvent) {
if (!(window.content.document instanceof ImageDocument)) {
if (!ImageDocument.isInstance(window.content.document)) {
return;
}
@ -523,7 +523,7 @@ var gGestureSupport = {
* Perform a rotation end for ImageDocuments
*/
rotateEnd() {
if (!(window.content.document instanceof ImageDocument)) {
if (!ImageDocument.isInstance(window.content.document)) {
return;
}
@ -607,7 +607,7 @@ var gGestureSupport = {
return;
}
if (!(window.content.document instanceof ImageDocument)) {
if (!ImageDocument.isInstance(window.content.document)) {
return;
}
@ -637,7 +637,7 @@ var gGestureSupport = {
_clearCompleteRotation() {
let contentElement =
window.content.document &&
window.content.document instanceof ImageDocument &&
ImageDocument.isInstance(window.content.document) &&
window.content.document.body &&
window.content.document.body.firstElementChild;
if (!contentElement) {

View file

@ -203,8 +203,8 @@ gImageView.getCellProperties = function(row, col) {
var props = "";
if (
!checkProtocol(data) ||
item instanceof HTMLEmbedElement ||
(item instanceof HTMLObjectElement && !item.type.startsWith("image/"))
HTMLEmbedElement.isInstance(item) ||
(HTMLObjectElement.isInstance(item) && !item.type.startsWith("image/"))
) {
props += "broken";
}
@ -720,9 +720,9 @@ function saveMedia() {
if (url) {
var titleKey = "SaveImageTitle";
if (item instanceof HTMLVideoElement) {
if (HTMLVideoElement.isInstance(item)) {
titleKey = "SaveVideoTitle";
} else if (item instanceof HTMLAudioElement) {
} else if (HTMLAudioElement.isInstance(item)) {
titleKey = "SaveAudioTitle";
}

View file

@ -1998,7 +1998,7 @@
if (isMovingTabs) {
let sourceNode = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
if (
sourceNode instanceof XULElement &&
XULElement.isInstance(sourceNode) &&
sourceNode.localName == "tab" &&
sourceNode.ownerGlobal.isChromeWindow &&
sourceNode.ownerDocument.documentElement.getAttribute("windowtype") ==

View file

@ -140,7 +140,7 @@ function performAccessKey(browser, key) {
callback,
{ capture: true },
event => {
if (!(event.target instanceof HTMLElement)) {
if (!HTMLElement.isInstance(event.target)) {
return false; // ignore window and document focus events
}

View file

@ -972,7 +972,7 @@ async function test_rotateGesturesOnTab() {
true
);
if (!(content.document instanceof ImageDocument)) {
if (!ImageDocument.isInstance(content.document)) {
ok(false, "Image document failed to open for rotation testing");
gBrowser.removeTab(test_imageTab);
BrowserTestUtils.removeTab(test_normalTab);

View file

@ -576,7 +576,7 @@ var gSearchResultsPane = {
// add it to the list of subitems. The items that don't match the search term
// will be hidden.
if (
child instanceof Element &&
Element.isInstance(child) &&
(child.classList.contains("featureGate") ||
child.classList.contains("mozilla-product-item"))
) {

View file

@ -54,7 +54,7 @@ class MarkupContextMenu {
show(event) {
if (
!(event.originalTarget instanceof Element) ||
!Element.isInstance(event.originalTarget) ||
event.originalTarget.closest("input[type=text]") ||
event.originalTarget.closest("input:not([type])") ||
event.originalTarget.closest("textarea")

View file

@ -1521,18 +1521,22 @@ Column.prototype = {
// Only sort the array if we are sorting based on this column
if (this.sorted == 1) {
items.sort((a, b) => {
const val1 =
a[this.id] instanceof Node ? a[this.id].textContent : a[this.id];
const val2 =
b[this.id] instanceof Node ? b[this.id].textContent : b[this.id];
const val1 = Node.isInstance(a[this.id])
? a[this.id].textContent
: a[this.id];
const val2 = Node.isInstance(b[this.id])
? b[this.id].textContent
: b[this.id];
return naturalSortCaseInsensitive(val1, val2);
});
} else if (this.sorted > 1) {
items.sort((a, b) => {
const val1 =
a[this.id] instanceof Node ? a[this.id].textContent : a[this.id];
const val2 =
b[this.id] instanceof Node ? b[this.id].textContent : b[this.id];
const val1 = Node.isInstance(a[this.id])
? a[this.id].textContent
: a[this.id];
const val2 = Node.isInstance(b[this.id])
? b[this.id].textContent
: b[this.id];
return naturalSortCaseInsensitive(val2, val1);
});
}
@ -1683,13 +1687,13 @@ Cell.prototype = {
return;
}
if (this.wrapTextInElements && !(value instanceof Node)) {
if (this.wrapTextInElements && !Node.isInstance(value)) {
const span = this.label.ownerDocument.createElementNS(HTML_NS, "span");
span.textContent = value;
value = span;
}
if (value instanceof Node) {
if (Node.isInstance(value)) {
this.label.removeAttribute("value");
while (this.label.firstChild) {

View file

@ -130,7 +130,7 @@ class LazyMessageList extends Component {
let element = this.#topBufferRef.current.nextSibling;
let elementRect = element?.getBoundingClientRect();
while (
element instanceof Element &&
Element.isInstance(element) &&
index < this.#clampedEndIndex &&
element !== this.#bottomBufferRef.current
) {

View file

@ -427,7 +427,7 @@ const NodeActor = protocol.ActorClassWithSpec(nodeSpec, {
// node with `name="attributes"` exists in the DOM we need to bail.
if (
!this.rawNode.attributes ||
!(this.rawNode.attributes instanceof NamedNodeMap)
!NamedNodeMap.isInstance(this.rawNode.attributes)
) {
return undefined;
}

View file

@ -14,8 +14,14 @@ These files are covered:
- ``*.js`` with a heuristic
Since there is no straightforward way to detect chrome scripts, currently the
linter assumes that any script including ``ChromeUtils`` is chrome privileged.
This of course may not be sufficient and is open for change.
linter assumes that any script including the following words are chrome
privileged. This of course may not be sufficient and is open for change:
- ``ChromeUtils``, but not ``SpecialPowers.ChromeUtils``
- ``BrowserTestUtils``, ``PlacesUtils``
- ``document.createXULElement``
- ``loader.lazyRequireGetter``
- ``Services.foo``, but not ``SpecialPowers.Services.foo``
Examples of incorrect code for this rule:
-----------------------------------------

View file

@ -13,7 +13,7 @@ async function observeAttached(callback) {
function observer(subject, topic, data) {
is(topic, TOPIC, "observing correct topic");
ok(subject instanceof BrowsingContext, "subject to be a BrowsingContext");
ok(BrowsingContext.isInstance(subject), "subject to be a BrowsingContext");
is(typeof data, "string", "data to be a String");
info(`*** bc id=${subject.id}, why=${data}`);
attached.set(subject.id, { browsingContext: subject, why: data });

View file

@ -6,7 +6,7 @@ async function observeDiscarded(browsingContexts, callback) {
let discarded = [];
let promise = BrowserUtils.promiseObserved(TOPIC, subject => {
ok(subject instanceof BrowsingContext, "subject to be a BrowsingContext");
ok(BrowsingContext.isInstance(subject), "subject to be a BrowsingContext");
discarded.push(subject);
return browsingContexts.every(item => discarded.includes(item));

View file

@ -79,7 +79,7 @@ add_task(async function test_structuredCloneHolder() {
res = await resultPromise;
ok(
res.data instanceof StructuredCloneHolder,
StructuredCloneHolder.isInstance(res.data),
"Sending structured clone holders through message managers works as expected"
);

View file

@ -41,7 +41,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=328885
inputelement.addEventListener('click',
function(event) {
var evt = SpecialPowers.wrap(event);
ok(SpecialPowers.call_Instanceof(evt.originalTarget, HTMLDivElement),
ok(SpecialPowers.wrap(HTMLDivElement).isInstance(evt.originalTarget),
"(1) Wrong originalTarget!");
is(SpecialPowers.unwrap(evt.originalTarget.parentNode), inputelement,
"(2) Wront parent node!");

View file

@ -51,7 +51,7 @@ add_task(async function test() {
});
});
ok(blob instanceof File, "We have a file");
ok(File.isInstance(blob), "We have a file");
is(blob.size, file.fileSize, "The size matches");
is(blob.name, file.leafName, "The name is correct");

View file

@ -54,7 +54,7 @@ add_task(async function testSteps() {
ok(false, "Should have thrown");
} catch (ex) {
ok(true, "Did throw");
ok(ex instanceof DOMException, "Threw DOMException");
ok(DOMException.isInstance(ex), "Threw DOMException");
is(ex.name, "QuotaExceededError", "Threw right DOMException");
is(ex.code, NS_ERROR_DOM_QUOTA_EXCEEDED_ERR, "Threw with right code");
}

View file

@ -63,7 +63,7 @@ add_task(async function testSteps() {
ok(false, "Should have thrown");
} catch (ex) {
ok(true, "Did throw");
ok(ex instanceof DOMException, "Threw DOMException");
ok(DOMException.isInstance(ex), "Threw DOMException");
is(ex.name, "QuotaExceededError", "Threw right DOMException");
is(ex.code, NS_ERROR_DOM_QUOTA_EXCEEDED_ERR, "Threw with right code");
}

View file

@ -77,7 +77,7 @@ async function addFrame(browser, path, selector) {
) {
let document = content.document;
let target = document.querySelector(selector);
if (target instanceof content.HTMLIFrameElement) {
if (content.HTMLIFrameElement.isInstance(target)) {
document = target.contentDocument;
target = document.body;
}

View file

@ -51,7 +51,7 @@ add_task(async function test() {
});
});
ok(blob instanceof File, "We have a file");
ok(File.isInstance(blob), "We have a file");
is(blob.size, file.fileSize, "The size matches");
is(blob.name, file.leafName, "The name is correct");

View file

@ -216,6 +216,7 @@ add_task(async function runtimeSendMessageReply() {
add_task(async function runtimeSendMessageBlob() {
function background() {
browser.runtime.onMessage.addListener(msg => {
// eslint-disable-next-line mozilla/use-isInstance -- this function runs in an extension
browser.test.assertTrue(msg.blob instanceof Blob, "Message is a blob");
return Promise.resolve(msg);
});
@ -230,6 +231,7 @@ add_task(async function runtimeSendMessageBlob() {
.sendMessage({ blob: new Blob(["hello"]) })
.then(response => {
browser.test.assertTrue(
// eslint-disable-next-line mozilla/use-isInstance -- this function runs in an extension
response.blob instanceof Blob,
"Response is a blob"
);

View file

@ -134,7 +134,7 @@ async function test_xhr({ manifest_version }) {
let x = await runXHR("http://example.com/dummy", {
responseType: "document",
});
browser.test.assertTrue(x.response instanceof HTMLDocument, "is doc");
browser.test.assertTrue(HTMLDocument.isInstance(x.response), "is doc");
browser.test.assertTrue(
x.response.querySelector("#id_of_some_element"),
"got parsed document"

View file

@ -137,13 +137,12 @@ add_task(async function test_returns_false_when_pref_disabled() {
// Use registration form test case, where we know it should return true if enabled
const testcase = TESTCASES[1];
info("Starting testcase: " + testcase.description);
const document =
testcase.document instanceof Document
? testcase.document
: MockDocument.createTestDocument(
"http://localhost:8080/test/",
testcase.document
);
const document = Document.isInstance(testcase.document)
? testcase.document
: MockDocument.createTestDocument(
"http://localhost:8080/test/",
testcase.document
);
for (let [i, input] of testcase.inputs ||
document.querySelectorAll(`input[type="password"]`).entries()) {
const result = LoginAutoComplete.isProbablyANewPasswordField(input);
@ -164,13 +163,12 @@ for (let testcase of TESTCASES) {
(function() {
add_task(async function() {
info("Starting testcase: " + testcase.description);
let document =
testcase.document instanceof Document
? testcase.document
: MockDocument.createTestDocument(
"http://localhost:8080/test/",
testcase.document
);
let document = Document.isInstance(testcase.document)
? testcase.document
: MockDocument.createTestDocument(
"http://localhost:8080/test/",
testcase.document
);
document = makeDocumentVisibleToFathom(document);

View file

@ -48,7 +48,7 @@ add_task(async function test_fetchMany() {
for (let key of keys) {
let page = pages.find(p => p.guid == key || p.url == key);
Assert.deepEqual(page, fetched.get(key));
Assert.ok(fetched.get(key).url instanceof URL);
Assert.ok(URL.isInstance(fetched.get(key).url));
}
});

View file

@ -37,8 +37,8 @@ const sandboxScript = function(shadowRoot) {
let doc = element.ownerDocument;
let win = doc.defaultView;
ok(shadowRoot instanceof win.ShadowRoot, "shadowRoot is a ShadowRoot");
ok(element instanceof win.HTMLDivElement, "Element is a <div>");
ok(win.ShadowRoot.isInstance(shadowRoot), "shadowRoot is a ShadowRoot");
ok(win.HTMLDivElement.isInstance(element), "Element is a <div>");
is("createElement" in doc, false, "No document.createElement");
is("createElementNS" in doc, false, "No document.createElementNS");
@ -67,7 +67,7 @@ const sandboxScript = function(shadowRoot) {
`<div xmlns="http://www.w3.org/1999/xhtml">Hello from DOMParser!</div>`, "application/xml");
shadowRoot.importNodeAndAppendChildAt(shadowRoot, parserDoc.documentElement, true);
ok(shadowRoot.lastChild instanceof win.HTMLDivElement, "<div> inserted");
ok(win.HTMLDivElement.isInstance(shadowRoot.lastChild), "<div> inserted");
is(shadowRoot.lastChild.textContent, "Hello from DOMParser!", "Deep import node worked");
info("UA Widget reflectors tests");
@ -78,8 +78,8 @@ const sandboxScript = function(shadowRoot) {
SpecialPowers.Cu.evalInSandbox("this.script = " + sandboxScript.toString(), sandbox);
sandbox.script(div.shadowRoot);
ok(SpecialPowers.call_Instanceof(window.spanElementFromUAWidget, HTMLSpanElement), "<span> exposed");
ok(SpecialPowers.call_Instanceof(window.divElementFromUAWidget, HTMLDivElement), "<div> exposed");
ok(SpecialPowers.wrap(HTMLSpanElement).isInstance(window.spanElementFromUAWidget), "<span> exposed");
ok(SpecialPowers.wrap(HTMLDivElement).isInstance(window.divElementFromUAWidget), "<div> exposed");
try {
window.spanElementFromUAWidget.textContent;

View file

@ -95,9 +95,17 @@ function isChromeContext(context) {
return fs.readFileSync(filename).includes("there.is.only.xul");
}
// Treat scripts using ChromeUtils as chrome scripts, but not SpecialPowers.ChromeUtils
// Treat scripts as chrome privileged when using:
// 1. ChromeUtils, but not SpecialPowers.ChromeUtils
// 2. BrowserTestUtils, PlacesUtils
// 3. document.createXULElement
// 4. loader.lazyRequireGetter
// 5. Services.foo, but not SpecialPowers.Services.foo
// 6. evalInSandbox
const source = context.getSourceCode().text;
return !!source.match(/(^|\s)ChromeUtils/);
return !!source.match(
/(^|\s)ChromeUtils|BrowserTestUtils|PlacesUtils|createXULElement|lazyRequireGetter|(^|\s)Services\.|evalInSandbox/
);
}
module.exports = {