зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1793534 - part 2: Make the accessibility module handle exposable URIs which do not contain user-pass section r=Jamie
We shouldn't expose the user-pass section of document URI to another apps since it's sensitive data, but non-malicious a11y API users must not need it. Additionally, `data` and `blob` URI may be too big (e.g., can be some mega bytes) and they may need to allocate too big string multiple times in the heap per URI. Therefore, the accessibility module should stop handling URI as-is if the document URI is one of them. Differential Revision: https://phabricator.services.mozilla.com/D158735
This commit is contained in:
Родитель
31375f07bd
Коммит
6b389daaf1
|
@ -15,6 +15,7 @@
|
|||
#include "nsAccessiblePivot.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsEventShell.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsTextEquivUtils.h"
|
||||
#include "Pivot.h"
|
||||
|
@ -42,6 +43,7 @@
|
|||
#include "nsTHashSet.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Components.h" // for mozilla::components
|
||||
#include "mozilla/EditorBase.h"
|
||||
#include "mozilla/HTMLEditor.h"
|
||||
#include "mozilla/ipc/ProcessChild.h"
|
||||
|
@ -341,15 +343,37 @@ already_AddRefed<EditorBase> DocAccessible::GetEditor() const {
|
|||
// DocAccessible public method
|
||||
|
||||
void DocAccessible::URL(nsAString& aURL) const {
|
||||
aURL.Truncate();
|
||||
nsCOMPtr<nsISupports> container = mDocumentNode->GetContainer();
|
||||
nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(container));
|
||||
nsAutoCString theURL;
|
||||
if (webNav) {
|
||||
nsCOMPtr<nsIURI> pURI;
|
||||
webNav->GetCurrentURI(getter_AddRefs(pURI));
|
||||
if (pURI) pURI->GetSpec(theURL);
|
||||
if (MOZ_UNLIKELY(!webNav)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
webNav->GetCurrentURI(getter_AddRefs(uri));
|
||||
if (MOZ_UNLIKELY(!uri)) {
|
||||
return;
|
||||
}
|
||||
// Let's avoid treating too long URI in the main process for avoiding
|
||||
// memory fragmentation as far as possible.
|
||||
if (uri->SchemeIs("data") || uri->SchemeIs("blob")) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIIOService> io = mozilla::components::IO::Service();
|
||||
if (NS_WARN_IF(!io)) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIURI> exposableURI;
|
||||
if (NS_FAILED(io->CreateExposableURI(uri, getter_AddRefs(exposableURI))) ||
|
||||
MOZ_UNLIKELY(!exposableURI)) {
|
||||
return;
|
||||
}
|
||||
nsAutoCString theURL;
|
||||
if (NS_SUCCEEDED(exposableURI->GetSpec(theURL))) {
|
||||
CopyUTF8toUTF16(theURL, aURL);
|
||||
}
|
||||
CopyUTF8toUTF16(theURL, aURL);
|
||||
}
|
||||
|
||||
void DocAccessible::Title(nsString& aTitle) const {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "CachedTableAccessible.h"
|
||||
#include "DocAccessibleParent.h"
|
||||
#include "mozilla/a11y/Platform.h"
|
||||
#include "mozilla/Components.h" // for mozilla::components
|
||||
#include "mozilla/dom/BrowserBridgeParent.h"
|
||||
#include "mozilla/dom/BrowserParent.h"
|
||||
#include "mozilla/dom/CanonicalBrowsingContext.h"
|
||||
|
@ -14,6 +15,7 @@
|
|||
#include "xpcAccessibleDocument.h"
|
||||
#include "xpcAccEvents.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "TextRange.h"
|
||||
#include "RootAccessible.h"
|
||||
|
||||
|
@ -1290,12 +1292,26 @@ void DocAccessibleParent::URL(nsAString& aURL) const {
|
|||
if (!mBrowsingContext) {
|
||||
return;
|
||||
}
|
||||
nsAutoCString url;
|
||||
nsCOMPtr<nsIURI> uri = mBrowsingContext->GetCurrentURI();
|
||||
if (!uri) {
|
||||
return;
|
||||
}
|
||||
uri->GetSpec(url);
|
||||
// Let's avoid treating too long URI in the main process for avoiding
|
||||
// memory fragmentation as far as possible.
|
||||
if (uri->SchemeIs("data") || uri->SchemeIs("blob")) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIIOService> io = mozilla::components::IO::Service();
|
||||
if (NS_WARN_IF(!io)) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIURI> exposableURI;
|
||||
if (NS_FAILED(io->CreateExposableURI(uri, getter_AddRefs(exposableURI))) ||
|
||||
MOZ_UNLIKELY(!exposableURI)) {
|
||||
return;
|
||||
}
|
||||
nsAutoCString url;
|
||||
exposableURI->GetSpec(url);
|
||||
CopyUTF8toUTF16(url, aURL);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,9 +36,7 @@ addAccessibleTask(`<title>webarea test</title>`, async (browser, accDoc) => {
|
|||
// document, we'll get one AXLoadComplete event.
|
||||
let eventPromise = Promise.race([
|
||||
waitForMacEvent("AXLayoutComplete", (iface, data) => {
|
||||
return (
|
||||
iface.getAttributeValue("AXDescription") == "data:text/html,hello world"
|
||||
);
|
||||
return iface.getAttributeValue("AXDescription") == "iframe document";
|
||||
}),
|
||||
waitForMacEvent("AXLoadComplete", (iface, data) => {
|
||||
return iface.getAttributeValue("AXDescription") == "webarea test";
|
||||
|
@ -46,7 +44,7 @@ addAccessibleTask(`<title>webarea test</title>`, async (browser, accDoc) => {
|
|||
]);
|
||||
await SpecialPowers.spawn(browser, [], () => {
|
||||
const iframe = content.document.createElement("iframe");
|
||||
iframe.src = "data:text/html,hello world";
|
||||
iframe.src = "data:text/html,<title>iframe document</title>hello world";
|
||||
content.document.body.appendChild(iframe);
|
||||
});
|
||||
let doc = await eventPromise;
|
||||
|
@ -67,7 +65,7 @@ addAccessibleTask(`<title>webarea test</title>`, async (browser, accDoc) => {
|
|||
is(doc.getAttributeValue("AXTitle"), null, "iframe document has no AXTitle");
|
||||
is(
|
||||
doc.getAttributeValue("AXDescription"),
|
||||
"data:text/html,hello world",
|
||||
"iframe document",
|
||||
"test has correct label"
|
||||
);
|
||||
|
||||
|
|
|
@ -12,3 +12,4 @@ skip-if = true || (verify && !debug && (os == 'linux')) #Bug 1445513
|
|||
[browser_lazy_tabs.js]
|
||||
[browser_searchbar.js]
|
||||
[browser_shadowdom.js]
|
||||
[browser_test_nsIAccessibleDocument_URL.js]
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
async function promiseEventDocumentLoadComplete(expectedURL) {
|
||||
return new Promise(resolve => {
|
||||
waitForEvent(EVENT_DOCUMENT_LOAD_COMPLETE, event => {
|
||||
try {
|
||||
if (
|
||||
event.accessible.QueryInterface(nsIAccessibleDocument).URL ==
|
||||
expectedURL
|
||||
) {
|
||||
resolve(event.accessible.QueryInterface(nsIAccessibleDocument));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
add_task(async function testInDataURI() {
|
||||
const kURL = "data:text/html,Some text";
|
||||
const waitForDocumentLoadComplete = promiseEventDocumentLoadComplete("");
|
||||
await BrowserTestUtils.withNewTab(kURL, async browser => {
|
||||
is(
|
||||
(await waitForDocumentLoadComplete).URL,
|
||||
"",
|
||||
"nsIAccessibleDocument.URL shouldn't return data URI"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function testInHTTPSURIContainingPrivateThings() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["network.auth.confirmAuth.enabled", false]],
|
||||
});
|
||||
const kURL =
|
||||
"https://username:password@example.com/browser/toolkit/content/tests/browser/file_empty.html?query=some#ref";
|
||||
const kURLWithoutUserPass =
|
||||
"https://example.com/browser/toolkit/content/tests/browser/file_empty.html?query=some#ref";
|
||||
const waitForDocumentLoadComplete = promiseEventDocumentLoadComplete(
|
||||
kURLWithoutUserPass
|
||||
);
|
||||
await BrowserTestUtils.withNewTab(kURL, async browser => {
|
||||
is(
|
||||
(await waitForDocumentLoadComplete).URL,
|
||||
kURLWithoutUserPass,
|
||||
"nsIAccessibleDocument.URL shouldn't contain user/pass section"
|
||||
);
|
||||
});
|
||||
});
|
Загрузка…
Ссылка в новой задаче