summaryrefslogtreecommitdiffstats
path: root/dom
diff options
context:
space:
mode:
Diffstat (limited to 'dom')
-rw-r--r--dom/canvas/CanvasRenderingContext2D.cpp29
-rw-r--r--dom/canvas/CanvasRenderingContext2D.h22
-rw-r--r--dom/locales/en-US/chrome/security/security.properties2
-rw-r--r--dom/security/nsContentSecurityUtils.cpp48
-rw-r--r--dom/security/test/general/browser.toml10
-rw-r--r--dom/security/test/general/browser_test_http_download.js275
-rw-r--r--dom/security/test/general/http_download_page.html23
-rw-r--r--dom/security/test/general/http_download_server.sjs20
-rw-r--r--dom/security/test/https-only/browser_save_as.js10
-rw-r--r--dom/security/test/mixedcontentblocker/browser_test_mixed_content_download.js2
-rw-r--r--dom/serviceworkers/test/browser_download.js2
11 files changed, 74 insertions, 369 deletions
diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp
index 529466cc81..62f6e6443d 100644
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -3463,7 +3463,9 @@ void CanvasRenderingContext2D::ArcTo(double aX1, double aY1, double aX2,
return aError.ThrowIndexSizeError("Negative radius");
}
- EnsureWritablePath();
+ if (!EnsureWritablePath()) {
+ return;
+ }
// Current point in user space!
Point p0 = mPathBuilder->CurrentPoint();
@@ -3535,7 +3537,9 @@ void CanvasRenderingContext2D::Arc(double aX, double aY, double aR,
return;
}
- EnsureWritablePath();
+ if (!EnsureWritablePath()) {
+ return;
+ }
EnsureActivePath();
@@ -3545,7 +3549,9 @@ void CanvasRenderingContext2D::Arc(double aX, double aY, double aR,
void CanvasRenderingContext2D::Rect(double aX, double aY, double aW,
double aH) {
- EnsureWritablePath();
+ if (!EnsureWritablePath()) {
+ return;
+ }
if (!std::isfinite(aX) || !std::isfinite(aY) || !std::isfinite(aW) ||
!std::isfinite(aH)) {
@@ -3741,7 +3747,9 @@ void CanvasRenderingContext2D::RoundRect(
const UnrestrictedDoubleOrDOMPointInitOrUnrestrictedDoubleOrDOMPointInitSequence&
aRadii,
ErrorResult& aError) {
- EnsureWritablePath();
+ if (!EnsureWritablePath()) {
+ return;
+ }
PathBuilder* builder = mPathBuilder;
Maybe<Matrix> transform = Nothing();
@@ -3759,7 +3767,9 @@ void CanvasRenderingContext2D::Ellipse(double aX, double aY, double aRadiusX,
return aError.ThrowIndexSizeError("Negative radius");
}
- EnsureWritablePath();
+ if (!EnsureWritablePath()) {
+ return;
+ }
ArcToBezier(this, Point(aX, aY), Size(aRadiusX, aRadiusY), aStartAngle,
aEndAngle, aAnticlockwise, aRotation);
@@ -3780,10 +3790,14 @@ void CanvasRenderingContext2D::FlushPathTransform() {
mPathTransformDirty = false;
}
-void CanvasRenderingContext2D::EnsureWritablePath() {
+bool CanvasRenderingContext2D::EnsureWritablePath() {
EnsureTarget();
+
// NOTE: IsTargetValid() may be false here (mTarget == sErrorTarget) but we
// go ahead and create a path anyway since callers depend on that.
+ if (NS_WARN_IF(!mTarget)) {
+ return false;
+ }
FillRule fillRule = CurrentState().fillRule;
@@ -3792,7 +3806,7 @@ void CanvasRenderingContext2D::EnsureWritablePath() {
}
if (mPathBuilder) {
- return;
+ return true;
}
if (!mPath) {
@@ -3800,6 +3814,7 @@ void CanvasRenderingContext2D::EnsureWritablePath() {
} else {
mPathBuilder = mPath->CopyToBuilder(fillRule);
}
+ return true;
}
void CanvasRenderingContext2D::EnsureUserSpacePath(
diff --git a/dom/canvas/CanvasRenderingContext2D.h b/dom/canvas/CanvasRenderingContext2D.h
index 75a57ab14f..bfcbfccec2 100644
--- a/dom/canvas/CanvasRenderingContext2D.h
+++ b/dom/canvas/CanvasRenderingContext2D.h
@@ -364,14 +364,18 @@ class CanvasRenderingContext2D : public nsICanvasRenderingContextInternal,
}
void ClosePath() {
- EnsureWritablePath();
+ if (!EnsureWritablePath()) {
+ return;
+ }
mPathBuilder->Close();
mPathPruned = false;
}
void MoveTo(double aX, double aY) {
- EnsureWritablePath();
+ if (!EnsureWritablePath()) {
+ return;
+ }
mozilla::gfx::Point pos(ToFloat(aX), ToFloat(aY));
if (!pos.IsFinite()) {
@@ -383,13 +387,17 @@ class CanvasRenderingContext2D : public nsICanvasRenderingContextInternal,
}
void LineTo(double aX, double aY) {
- EnsureWritablePath();
+ if (!EnsureWritablePath()) {
+ return;
+ }
LineTo(mozilla::gfx::Point(ToFloat(aX), ToFloat(aY)));
}
void QuadraticCurveTo(double aCpx, double aCpy, double aX, double aY) {
- EnsureWritablePath();
+ if (!EnsureWritablePath()) {
+ return;
+ }
mozilla::gfx::Point cp1(ToFloat(aCpx), ToFloat(aCpy));
mozilla::gfx::Point cp2(ToFloat(aX), ToFloat(aY));
@@ -408,7 +416,9 @@ class CanvasRenderingContext2D : public nsICanvasRenderingContextInternal,
void BezierCurveTo(double aCp1x, double aCp1y, double aCp2x, double aCp2y,
double aX, double aY) {
- EnsureWritablePath();
+ if (!EnsureWritablePath()) {
+ return;
+ }
BezierTo(mozilla::gfx::Point(ToFloat(aCp1x), ToFloat(aCp1y)),
mozilla::gfx::Point(ToFloat(aCp2x), ToFloat(aCp2y)),
@@ -680,7 +690,7 @@ class CanvasRenderingContext2D : public nsICanvasRenderingContextInternal,
/* This function ensures there is a writable pathbuilder available
*/
- void EnsureWritablePath();
+ bool EnsureWritablePath();
// Ensures a path in UserSpace is available.
void EnsureUserSpacePath(
diff --git a/dom/locales/en-US/chrome/security/security.properties b/dom/locales/en-US/chrome/security/security.properties
index fc58fe4f7d..c19fc2d2bf 100644
--- a/dom/locales/en-US/chrome/security/security.properties
+++ b/dom/locales/en-US/chrome/security/security.properties
@@ -44,7 +44,7 @@ LoadingMixedActiveContent2=Loading mixed (insecure) active content “%1$S” on
LoadingMixedDisplayContent2=Loading mixed (insecure) display content “%1$S” on a secure page
LoadingMixedDisplayObjectSubrequestDeprecation=Loading mixed (insecure) content “%1$S” within a plugin on a secure page is discouraged and will be blocked soon.
# LOCALIZATION NOTE: "%S" is the URI of the insecure mixed content download
-BlockedInsecureDownload = We blocked a download that’s not secure: “%S”.
+MixedContentBlockedDownload = Blocked downloading insecure content “%S”.
# LOCALIZATION NOTE: Do not translate "allow-scripts", "allow-same-origin", "sandbox" or "iframe"
BothAllowScriptsAndSameOriginPresent=An iframe which has both allow-scripts and allow-same-origin for its sandbox attribute can remove its sandboxing.
diff --git a/dom/security/nsContentSecurityUtils.cpp b/dom/security/nsContentSecurityUtils.cpp
index 01e9c6d5db..d2c1b257bc 100644
--- a/dom/security/nsContentSecurityUtils.cpp
+++ b/dom/security/nsContentSecurityUtils.cpp
@@ -1670,25 +1670,37 @@ long nsContentSecurityUtils::ClassifyDownload(
nsCOMPtr<nsIURI> contentLocation;
aChannel->GetURI(getter_AddRefs(contentLocation));
- if (StaticPrefs::dom_block_download_insecure()) {
- // If we are not dealing with a potentially trustworthy origin, or a URI
- // that is safe to be loaded like e.g. data:, then we block the load.
- bool isInsecureDownload =
- !nsMixedContentBlocker::IsPotentiallyTrustworthyOrigin(
- contentLocation) &&
- !nsMixedContentBlocker::URISafeToBeLoadedInSecureContext(
- contentLocation);
-
- Telemetry::Accumulate(mozilla::Telemetry::INSECURE_DOWNLOADS,
- isInsecureDownload);
-
- if (isInsecureDownload) {
- nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
- if (httpChannel) {
- LogMessageToConsole(httpChannel, "BlockedInsecureDownload");
- }
- return nsITransfer::DOWNLOAD_POTENTIALLY_UNSAFE;
+ nsCOMPtr<nsIPrincipal> loadingPrincipal = loadInfo->GetLoadingPrincipal();
+ if (!loadingPrincipal) {
+ loadingPrincipal = loadInfo->TriggeringPrincipal();
+ }
+ // Creating a fake Loadinfo that is just used for the MCB check.
+ nsCOMPtr<nsILoadInfo> secCheckLoadInfo = new mozilla::net::LoadInfo(
+ loadingPrincipal, loadInfo->TriggeringPrincipal(), nullptr,
+ nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK,
+ nsIContentPolicy::TYPE_FETCH);
+ // Disable HTTPS-Only checks for that loadinfo. This is required because
+ // otherwise nsMixedContentBlocker::ShouldLoad would assume that the request
+ // is safe, because HTTPS-Only is handling it.
+ secCheckLoadInfo->SetHttpsOnlyStatus(nsILoadInfo::HTTPS_ONLY_EXEMPT);
+
+ int16_t decission = nsIContentPolicy::ACCEPT;
+ nsMixedContentBlocker::ShouldLoad(false, // aHadInsecureImageRedirect
+ contentLocation, // aContentLocation,
+ secCheckLoadInfo, // aLoadinfo
+ false, // aReportError
+ &decission // aDecision
+ );
+ Telemetry::Accumulate(mozilla::Telemetry::MIXED_CONTENT_DOWNLOADS,
+ decission != nsIContentPolicy::ACCEPT);
+
+ if (StaticPrefs::dom_block_download_insecure() &&
+ decission != nsIContentPolicy::ACCEPT) {
+ nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
+ if (httpChannel) {
+ LogMessageToConsole(httpChannel, "MixedContentBlockedDownload");
}
+ return nsITransfer::DOWNLOAD_POTENTIALLY_UNSAFE;
}
if (loadInfo->TriggeringPrincipal()->IsSystemPrincipal()) {
diff --git a/dom/security/test/general/browser.toml b/dom/security/test/general/browser.toml
index c6d6b4bf79..0f4ec5b224 100644
--- a/dom/security/test/general/browser.toml
+++ b/dom/security/test/general/browser.toml
@@ -48,16 +48,6 @@ support-files = [
"file_gpc_server.sjs",
]
-["browser_test_http_download.js"]
-skip-if = [
- "win11_2009", # Bug 1784764
- "os == 'linux' && !debug",
-]
-support-files = [
- "http_download_page.html",
- "http_download_server.sjs"
-]
-
["browser_test_referrer_loadInOtherProcess.js"]
["browser_test_report_blocking.js"]
diff --git a/dom/security/test/general/browser_test_http_download.js b/dom/security/test/general/browser_test_http_download.js
deleted file mode 100644
index 35e3fdfc4b..0000000000
--- a/dom/security/test/general/browser_test_http_download.js
+++ /dev/null
@@ -1,275 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * https://creativecommons.org/publicdomain/zero/1.0/ */
-
-ChromeUtils.defineESModuleGetters(this, {
- Downloads: "resource://gre/modules/Downloads.sys.mjs",
- DownloadsCommon: "resource:///modules/DownloadsCommon.sys.mjs",
-});
-
-const HandlerService = Cc[
- "@mozilla.org/uriloader/handler-service;1"
-].getService(Ci.nsIHandlerService);
-
-const MIMEService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
-
-// Using insecure HTTP URL for a test cases around HTTP downloads
-let INSECURE_BASE_URL =
- getRootDirectory(gTestPath).replace(
- "chrome://mochitests/content/",
- // eslint-disable-next-line @microsoft/sdl/no-insecure-url
- "http://example.com/"
- ) + "http_download_page.html";
-
-function promiseFocus() {
- return new Promise(resolve => {
- waitForFocus(resolve);
- });
-}
-
-async function task_openPanel() {
- await promiseFocus();
-
- let promise = BrowserTestUtils.waitForPopupEvent(
- DownloadsPanel.panel,
- "shown"
- );
- DownloadsPanel.showPanel();
- await promise;
-}
-
-const downloadMonitoringView = {
- _listeners: [],
- onDownloadAdded(download) {
- for (let listener of this._listeners) {
- listener(download);
- }
- this._listeners = [];
- },
- waitForDownload(listener) {
- this._listeners.push(listener);
- },
-};
-
-/**
- * Waits until a download is triggered.
- * Unless the always_ask_before_handling_new_types pref is true, the download
- * will simply be saved, so resolve when the view is notified of the new
- * download. Otherwise, it waits until a prompt is shown, selects the choosen
- * <action>, then accepts the dialog
- * @param [action] Which action to select, either:
- * "handleInternally", "save" or "open".
- * @returns {Promise} Resolved once done.
- */
-
-function shouldTriggerDownload(action = "save") {
- if (
- Services.prefs.getBoolPref(
- "browser.download.always_ask_before_handling_new_types"
- )
- ) {
- return new Promise((resolve, reject) => {
- Services.wm.addListener({
- onOpenWindow(xulWin) {
- Services.wm.removeListener(this);
- let win = xulWin.docShell.domWindow;
- waitForFocus(() => {
- if (
- win.location ==
- "chrome://mozapps/content/downloads/unknownContentType.xhtml"
- ) {
- let dialog = win.document.getElementById("unknownContentType");
- let button = dialog.getButton("accept");
- let actionRadio = win.document.getElementById(action);
- actionRadio.click();
- button.disabled = false;
- dialog.acceptDialog();
- resolve();
- } else {
- reject();
- }
- }, win);
- },
- });
- });
- }
- return new Promise(res => {
- downloadMonitoringView.waitForDownload(res);
- });
-}
-
-const CONSOLE_ERROR_MESSAGE = "We blocked a download that’s not secure";
-
-function shouldConsoleError() {
- // Waits until CONSOLE_ERROR_MESSAGE was logged
- return new Promise((resolve, reject) => {
- function listener(msgObj) {
- let text = msgObj.message;
- if (text.includes(CONSOLE_ERROR_MESSAGE)) {
- Services.console.unregisterListener(listener);
- resolve();
- }
- }
- Services.console.registerListener(listener);
- });
-}
-
-async function resetDownloads() {
- // Removes all downloads from the download List
- const types = new Set();
- let publicList = await Downloads.getList(Downloads.PUBLIC);
- let downloads = await publicList.getAll();
- for (let download of downloads) {
- if (download.contentType) {
- types.add(download.contentType);
- }
- publicList.remove(download);
- await download.finalize(true);
- }
-
- if (types.size) {
- // reset handlers for the contentTypes of any files previously downloaded
- for (let type of types) {
- const mimeInfo = MIMEService.getFromTypeAndExtension(type, "");
- info("resetting handler for type: " + type);
- HandlerService.remove(mimeInfo);
- }
- }
-}
-
-function shouldNotifyDownloadUI() {
- return new Promise(res => {
- downloadMonitoringView.waitForDownload(async aDownload => {
- let { error } = aDownload;
- if (
- error.becauseBlockedByReputationCheck &&
- error.reputationCheckVerdict == Downloads.Error.BLOCK_VERDICT_INSECURE
- ) {
- // It's an insecure Download, now Check that it has been cleaned up properly
- if ((await IOUtils.stat(aDownload.target.path)).size != 0) {
- throw new Error(`Download target is not empty!`);
- }
- if ((await IOUtils.stat(aDownload.target.path)).size != 0) {
- throw new Error(`Download partFile was not cleaned up properly`);
- }
- // Assert that the Referrer is presnt
- if (!aDownload.source.referrerInfo) {
- throw new Error("The Blocked download is missing the ReferrerInfo");
- }
-
- res(aDownload);
- } else {
- ok(false, "No error for download that was expected to error!");
- }
- });
- });
-}
-
-async function runTest(url, link, checkFunction, description) {
- await SpecialPowers.pushPrefEnv({
- set: [["dom.block_download_insecure", true]],
- });
- await resetDownloads();
-
- let tab = BrowserTestUtils.addTab(gBrowser, url);
- gBrowser.selectedTab = tab;
-
- let browser = gBrowser.getBrowserForTab(tab);
- await BrowserTestUtils.browserLoaded(browser);
-
- info("Checking: " + description);
-
- let checkPromise = checkFunction();
- // Click the Link to trigger the download
- SpecialPowers.spawn(gBrowser.selectedBrowser, [link], contentLink => {
- content.document.getElementById(contentLink).click();
- });
-
- await checkPromise;
-
- ok(true, description);
- BrowserTestUtils.removeTab(tab);
-
- await SpecialPowers.popPrefEnv();
-}
-
-add_setup(async () => {
- let list = await Downloads.getList(Downloads.ALL);
- list.addView(downloadMonitoringView);
- registerCleanupFunction(() => list.removeView(downloadMonitoringView));
-});
-
-// Test Blocking
-add_task(async function test_blocking() {
- for (let prefVal of [true, false]) {
- await SpecialPowers.pushPrefEnv({
- set: [["browser.download.always_ask_before_handling_new_types", prefVal]],
- });
- await runTest(
- INSECURE_BASE_URL,
- "http-link",
- () =>
- Promise.all([
- shouldTriggerDownload(),
- shouldNotifyDownloadUI(),
- shouldConsoleError(),
- ]),
- "Insecure (HTTP) toplevel -> Insecure (HTTP) download should Error"
- );
- await SpecialPowers.popPrefEnv();
- }
-});
-
-// Test Manual Unblocking
-add_task(async function test_manual_unblocking() {
- for (let prefVal of [true, false]) {
- await SpecialPowers.pushPrefEnv({
- set: [["browser.download.always_ask_before_handling_new_types", prefVal]],
- });
- await runTest(
- INSECURE_BASE_URL,
- "http-link",
- async () => {
- let [, download] = await Promise.all([
- shouldTriggerDownload(),
- shouldNotifyDownloadUI(),
- ]);
- await download.unblock();
- Assert.equal(
- download.error,
- null,
- "There should be no error after unblocking"
- );
- },
- "A blocked download should succeed to download after a manual unblock"
- );
- await SpecialPowers.popPrefEnv();
- }
-});
-
-// Test Unblock Download Visible
-add_task(async function test_unblock_download_visible() {
- for (let prefVal of [true, false]) {
- await SpecialPowers.pushPrefEnv({
- set: [["browser.download.always_ask_before_handling_new_types", prefVal]],
- });
- await promiseFocus();
- await runTest(
- INSECURE_BASE_URL,
- "http-link",
- async () => {
- let panelHasOpened = BrowserTestUtils.waitForPopupEvent(
- DownloadsPanel.panel,
- "shown"
- );
- info("awaiting that the download is triggered and added to the list");
- await Promise.all([shouldTriggerDownload(), shouldNotifyDownloadUI()]);
- info("awaiting that the Download list shows itself");
- await panelHasOpened;
- DownloadsPanel.hidePanel();
- ok(true, "The Download Panel should have opened on blocked download");
- },
- "A blocked download should open the download panel"
- );
- await SpecialPowers.popPrefEnv();
- }
-});
diff --git a/dom/security/test/general/http_download_page.html b/dom/security/test/general/http_download_page.html
deleted file mode 100644
index c5461eaed3..0000000000
--- a/dom/security/test/general/http_download_page.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE HTML>
-<html>
- <head>
- <title>Test for the download attribute</title>
- </head>
- <body>
- hi
-
- <script>
- const host = window.location.host;
- const path = location.pathname.replace("http_download_page.html","http_download_server.sjs");
-
- const insecureLink = document.createElement("a");
- // eslint-disable-next-line @microsoft/sdl/no-insecure-url
- insecureLink.href=`http://${host}/${path}`;
- insecureLink.download="true";
- insecureLink.id="http-link";
- insecureLink.textContent="Not secure Link";
-
- document.body.append(insecureLink);
- </script>
- </body>
-</html>
diff --git a/dom/security/test/general/http_download_server.sjs b/dom/security/test/general/http_download_server.sjs
deleted file mode 100644
index e659df2f40..0000000000
--- a/dom/security/test/general/http_download_server.sjs
+++ /dev/null
@@ -1,20 +0,0 @@
-// force the Browser to Show a Download Prompt
-
-function handleRequest(request, response) {
- let type = "image/png";
- let filename = "hello.png";
- request.queryString.split("&").forEach(val => {
- var [key, value] = val.split("=");
- if (key == "type") {
- type = value;
- }
- if (key == "name") {
- filename = value;
- }
- });
-
- response.setHeader("Cache-Control", "no-cache", false);
- response.setHeader("Content-Disposition", `attachment; filename=${filename}`);
- response.setHeader("Content-Type", type);
- response.write("🙈🙊🐵🙊");
-}
diff --git a/dom/security/test/https-only/browser_save_as.js b/dom/security/test/https-only/browser_save_as.js
index fbfdf276a8..28f3df539d 100644
--- a/dom/security/test/https-only/browser_save_as.js
+++ b/dom/security/test/https-only/browser_save_as.js
@@ -155,11 +155,7 @@ async function setHttpsFirstAndOnlyPrefs(httpsFirst, httpsOnly) {
add_task(async function testBaseline() {
// Run with HTTPS-First and HTTPS-Only disabled
await setHttpsFirstAndOnlyPrefs(false, false);
- await runTest(
- "#insecure-link",
- HTTP_LINK,
- "We blocked a download that’s not secure: “http://example.org/”."
- );
+ await runTest("#insecure-link", HTTP_LINK, undefined);
await runTest("#secure-link", HTTPS_LINK, undefined);
});
@@ -173,7 +169,7 @@ add_task(async function testHttpsFirst() {
await runTest(
"#insecure-link",
HTTP_LINK,
- "We blocked a download that’s not secure: “http://example.org/”."
+ "Blocked downloading insecure content “http://example.org/”."
);
await runTest("#secure-link", HTTPS_LINK, undefined);
});
@@ -185,7 +181,7 @@ add_task(async function testHttpsOnly() {
await runTest(
"#insecure-link",
HTTP_LINK,
- "We blocked a download that’s not secure: “http://example.org/”."
+ "Blocked downloading insecure content “http://example.org/”."
);
await runTest("#secure-link", HTTPS_LINK, undefined);
});
diff --git a/dom/security/test/mixedcontentblocker/browser_test_mixed_content_download.js b/dom/security/test/mixedcontentblocker/browser_test_mixed_content_download.js
index b103d83cd7..ee350008aa 100644
--- a/dom/security/test/mixedcontentblocker/browser_test_mixed_content_download.js
+++ b/dom/security/test/mixedcontentblocker/browser_test_mixed_content_download.js
@@ -101,7 +101,7 @@ function shouldTriggerDownload(action = "save") {
});
}
-const CONSOLE_ERROR_MESSAGE = "We blocked a download that’s not secure";
+const CONSOLE_ERROR_MESSAGE = "Blocked downloading insecure content";
function shouldConsoleError() {
// Waits until CONSOLE_ERROR_MESSAGE was logged
diff --git a/dom/serviceworkers/test/browser_download.js b/dom/serviceworkers/test/browser_download.js
index 70622a2349..0c69a48d17 100644
--- a/dom/serviceworkers/test/browser_download.js
+++ b/dom/serviceworkers/test/browser_download.js
@@ -3,7 +3,7 @@
var gTestRoot = getRootDirectory(gTestPath).replace(
"chrome://mochitests/content/",
- "https://example.com/"
+ "http://mochi.test:8888/"
);
function getFile(aFilename) {