Commit a54ec307 authored by Bogdan Tara's avatar Bogdan Tara
Browse files

Backed out 4 changesets (bug 1631405) for multiple mochitest failures CLOSED TREE

Backed out changeset 9963cc0b23cb (bug 1631405)
Backed out changeset 469ac933ed7c (bug 1631405)
Backed out changeset 0c5f55864268 (bug 1631405)
Backed out changeset 20dcbcc2f3b8 (bug 1631405)
parent 6ed3c943
......@@ -82,6 +82,7 @@ tags = mcb
support-files =
test-mixedcontent-securityerrors.html
[browser_mixedContentFramesOnHttp.js]
fail-if = fission
tags = mcb
support-files =
file_mixedContentFramesOnHttp.html
......
......@@ -37,6 +37,28 @@ add_task(async function blockMixedActiveContentTest() {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URI);
gTestBrowser = gBrowser.getBrowserForTab(tab);
await SpecialPowers.spawn(gTestBrowser, [], function() {
is(
docShell.hasMixedDisplayContentBlocked,
false,
"hasMixedDisplayContentBlocked flag has been set"
);
is(
docShell.hasMixedActiveContentBlocked,
true,
"hasMixedActiveContentBlocked flag has been set"
);
is(
docShell.hasMixedDisplayContentLoaded,
true,
"hasMixedDisplayContentLoaded flag has been set"
);
is(
docShell.hasMixedActiveContentLoaded,
false,
"hasMixedActiveContentLoaded flag has been set"
);
});
await assertMixedContentBlockingState(gTestBrowser, {
activeLoaded: false,
activeBlocked: true,
......@@ -50,6 +72,28 @@ add_task(async function blockMixedActiveContentTest() {
gBrowser.reload();
await BrowserTestUtils.browserLoaded(gTestBrowser);
await SpecialPowers.spawn(gTestBrowser, [], function() {
is(
docShell.hasMixedDisplayContentBlocked,
true,
"hasMixedDisplayContentBlocked flag has been set"
);
is(
docShell.hasMixedActiveContentBlocked,
true,
"hasMixedActiveContentBlocked flag has been set"
);
is(
docShell.hasMixedDisplayContentLoaded,
false,
"hasMixedDisplayContentLoaded flag has been set"
);
is(
docShell.hasMixedActiveContentLoaded,
false,
"hasMixedActiveContentLoaded flag has been set"
);
});
await assertMixedContentBlockingState(gTestBrowser, {
activeLoaded: false,
activeBlocked: true,
......@@ -63,6 +107,28 @@ add_task(async function overrideMCB() {
gIdentityHandler.disableMixedContentProtection();
await BrowserTestUtils.browserLoaded(gTestBrowser);
await SpecialPowers.spawn(gTestBrowser, [], function() {
is(
docShell.hasMixedDisplayContentLoaded,
true,
"hasMixedDisplayContentLoaded flag has not been set"
);
is(
docShell.hasMixedActiveContentLoaded,
true,
"hasMixedActiveContentLoaded flag has not been set"
);
is(
docShell.hasMixedDisplayContentBlocked,
false,
"second hasMixedDisplayContentBlocked flag has been set"
);
is(
docShell.hasMixedActiveContentBlocked,
false,
"second hasMixedActiveContentBlocked flag has been set"
);
});
await assertMixedContentBlockingState(gTestBrowser, {
activeLoaded: true,
activeBlocked: false,
......
......@@ -55,6 +55,19 @@ add_task(async function allowLoopbackMixedContent() {
const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
const browser = gBrowser.getBrowserForTab(tab);
await SpecialPowers.spawn(browser, [], function() {
is(
docShell.hasMixedDisplayContentBlocked,
false,
"hasMixedDisplayContentBlocked not set"
);
is(
docShell.hasMixedActiveContentBlocked,
false,
"hasMixedActiveContentBlocked not set"
);
});
// Check that loopback content served from the cache is not blocked.
await SpecialPowers.spawn(browser, [LOOPBACK_PNG_URL], async function(
loopbackPNGUrl
......
......@@ -33,6 +33,19 @@ add_task(async function allowOnionMixedContent() {
).catch(Cu.reportError);
const browser = gBrowser.getBrowserForTab(tab);
await SpecialPowers.spawn(browser, [], function() {
is(
docShell.hasMixedDisplayContentBlocked,
false,
"hasMixedDisplayContentBlocked not set"
);
is(
docShell.hasMixedActiveContentBlocked,
false,
"hasMixedActiveContentBlocked not set"
);
});
await assertMixedContentBlockingState(browser, {
activeBlocked: false,
activeLoaded: false,
......
......@@ -11,23 +11,23 @@
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript">
async function checkLoadStates() {
let state = await SpecialPowers.getSecurityState(window);
function checkLoadStates() {
var ui = SpecialPowers.wrap(window).docShell.securityUI;
var loadedMixedActive =
!!(state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT);
var loadedMixedActive = ui &&
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT);
is(loadedMixedActive, false, "OK: Should not load mixed active content!");
var blockedMixedActive =
!!(state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT);
var blockedMixedActive = ui &&
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT);
is(blockedMixedActive, false, "OK: Should not block mixed active content!");
var loadedMixedDisplay =
!!(state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT);
var loadedMixedDisplay = ui &&
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT);
is(loadedMixedDisplay, false, "OK: Should not load mixed display content!");
var blockedMixedDisplay =
!!(state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_DISPLAY_CONTENT);
var blockedMixedDisplay = ui &&
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_DISPLAY_CONTENT);
is(blockedMixedDisplay, false, "OK: Should not block mixed display content!");
var newValue = "Verifying MCB does not trigger warning/error for an http page with https css that includes http font";
......
......@@ -11,23 +11,23 @@
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript">
async function checkLoadStates() {
let state = await SpecialPowers.getSecurityState(window);
function checkLoadStates() {
var ui = SpecialPowers.wrap(window).docShell.securityUI;
var loadedMixedActive =
!!(state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT);
var loadedMixedActive = ui &&
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT);
is(loadedMixedActive, false, "OK: Should not load mixed active content!");
var blockedMixedActive =
!!(state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT);
var blockedMixedActive = ui &&
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT);
is(blockedMixedActive, false, "OK: Should not block mixed active content!");
var loadedMixedDisplay =
!!(state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT);
var loadedMixedDisplay = ui &&
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT);
is(loadedMixedDisplay, false, "OK: Should not load mixed display content!");
var blockedMixedDisplay =
!!(state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_DISPLAY_CONTENT);
var blockedMixedDisplay = ui &&
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_DISPLAY_CONTENT);
is(blockedMixedDisplay, false, "OK: Should not block mixed display content!");
var newValue = "Verifying MCB does not trigger warning/error for an http page ";
......
......@@ -11,23 +11,23 @@
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript">
async function checkLoadStates() {
let state = await SpecialPowers.getSecurityState(window);
function checkLoadStates() {
var ui = SpecialPowers.wrap(window).docShell.securityUI;
var loadedMixedActive =
!!(state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT);
var loadedMixedActive = ui &&
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT);
is(loadedMixedActive, false, "OK: Should not load mixed active content!");
var blockedMixedActive =
!!(state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT);
var blockedMixedActive = ui &&
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT);
is(blockedMixedActive, false, "OK: Should not block mixed active content!");
var loadedMixedDisplay =
!!(state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT);
var loadedMixedDisplay = ui &&
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT);
is(loadedMixedDisplay, false, "OK: Should not load mixed display content!");
var blockedMixedDisplay =
!!(state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_DISPLAY_CONTENT);
var blockedMixedDisplay = ui &&
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_DISPLAY_CONTENT);
is(blockedMixedDisplay, false, "OK: Should not block mixed display content!");
var newValue = "Verifying MCB does not trigger warning/error for an http page with https css that includes http image";
......
......@@ -148,6 +148,8 @@ class ReportSiteIssueHelperChild extends JSWindowActorChild {
case "GetBlockingStatus":
const { docShell } = this;
return {
hasMixedActiveContentBlocked: docShell.hasMixedActiveContentBlocked,
hasMixedDisplayContentBlocked: docShell.hasMixedDisplayContentBlocked,
hasTrackingContentBlocked: docShell.hasTrackingContentBlocked,
};
}
......
......@@ -31,14 +31,6 @@ this.tabExtras = class extends ExtensionAPI {
const promises = actors.map(actor => actor.sendQuery("GetLog"));
const logs = await Promise.all(promises);
const info = await actors[0].sendQuery("GetBlockingStatus");
info.hasMixedActiveContentBlocked = !!(
browsingContext.secureBrowserUI.state &
Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT
);
info.hasMixedDisplayContentBlocked = !!(
browsingContext.secureBrowserUI.state &
Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_DISPLAY_CONTENT
);
info.log = logs
.flat()
.sort((a, b) => a.timeStamp - b.timeStamp)
......
......@@ -85,6 +85,16 @@ add_task(async function test_opened_page() {
);
let docShell = content.docShell;
is(
typeof docShell.hasMixedActiveContentBlocked,
"boolean",
"docShell.hasMixedActiveContentBlocked is available"
);
is(
typeof docShell.hasMixedDisplayContentBlocked,
"boolean",
"docShell.hasMixedDisplayContentBlocked is available"
);
is(
typeof docShell.getHasTrackingContentBlocked,
"function",
......
......@@ -9,7 +9,6 @@
#include "ipc/IPCMessageUtils.h"
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/dom/BrowserParent.h"
#include "mozilla/dom/BrowsingContextGroup.h"
#include "mozilla/dom/BrowsingContextBinding.h"
#include "mozilla/dom/ContentChild.h"
......
......@@ -26,7 +26,6 @@
#include "nsIWebBrowserChrome.h"
#include "nsNetUtil.h"
#include "nsSHistory.h"
#include "nsSecureBrowserUI.h"
using namespace mozilla::ipc;
......@@ -115,23 +114,6 @@ void CanonicalBrowsingContext::SetOwnerProcessId(uint64_t aProcessId) {
mProcessId = aProcessId;
}
nsISecureBrowserUI* CanonicalBrowsingContext::GetSecureBrowserUI() {
if (!IsTop()) {
return nullptr;
}
if (!mSecureBrowserUI) {
mSecureBrowserUI = new nsSecureBrowserUI(this);
}
return mSecureBrowserUI;
}
void CanonicalBrowsingContext::
UpdateSecurityStateForLocationOrMixedContentChange() {
if (mSecureBrowserUI) {
mSecureBrowserUI->UpdateForLocationOrMixedContentChange();
}
}
void CanonicalBrowsingContext::SetInFlightProcessId(uint64_t aProcessId) {
// We can't handle more than one in-flight process change at a time.
MOZ_ASSERT_IF(aProcessId, mInFlightProcessId == 0);
......
......@@ -18,9 +18,7 @@
#include "nsHashKeys.h"
class nsISHistory;
#include "nsISecureBrowserUI.h"
class nsSecureBrowserUI;
namespace mozilla {
namespace net {
class DocumentLoadListener;
......@@ -143,15 +141,6 @@ class CanonicalBrowsingContext final : public BrowsingContext {
bool AttemptLoadURIInParent(nsDocShellLoadState* aLoadState,
uint32_t* aLoadIdentifier);
// Get or create a secure browser UI for this BrowsingContext
nsISecureBrowserUI* GetSecureBrowserUI();
// Called when the current URI changes (from an
// nsIWebProgressListener::OnLocationChange event, so that we
// can update our security UI for the new location, or when the
// mixed content state for our current window is changed.
void UpdateSecurityStateForLocationOrMixedContentChange();
protected:
// Called when the browsing context is being discarded.
void CanonicalDiscard();
......@@ -227,8 +216,6 @@ class CanonicalBrowsingContext final : public BrowsingContext {
nsTArray<SessionHistoryEntryAndId> mLoadingEntries;
RefPtr<SessionHistoryEntry> mActiveEntry;
RefPtr<nsSecureBrowserUI> mSecureBrowserUI;
};
} // namespace dom
......
......@@ -218,24 +218,6 @@ void WindowContext::Discard() {
Group()->Unregister(this);
}
void WindowContext::AddMixedContentSecurityState(uint32_t aStateFlags) {
MOZ_ASSERT(TopWindowContext() == this);
MOZ_ASSERT((aStateFlags &
(nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT |
nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT |
nsIWebProgressListener::STATE_BLOCKED_MIXED_DISPLAY_CONTENT |
nsIWebProgressListener::STATE_BLOCKED_MIXED_ACTIVE_CONTENT)) ==
aStateFlags,
"Invalid flags specified!");
if (XRE_IsParentProcess()) {
Canonical()->AddMixedContentSecurityState(aStateFlags);
} else {
ContentChild* child = ContentChild::GetSingleton();
child->SendAddMixedContentSecurityState(this, aStateFlags);
}
}
WindowContext::IPCInitializer WindowContext::GetIPCInitializer() {
IPCInitializer init;
init.mInnerWindowId = mInnerWindowId;
......
......@@ -16,7 +16,6 @@ namespace dom {
class WindowGlobalParent;
class WindowGlobalInit;
class BrowsingContextGroup;
#define MOZ_EACH_WC_FIELD(FIELD) \
FIELD(CookieBehavior, Maybe<uint32_t>) \
......@@ -92,12 +91,6 @@ class WindowContext : public nsISupports, public nsWrapperCache {
static void CreateFromIPC(IPCInitializer&& aInit);
// Add new mixed content security state flags.
// These should be some of the four nsIWebProgressListener
// 'MIXED' state flags, and should only be called on the
// top window context.
void AddMixedContentSecurityState(uint32_t aStateFlags);
protected:
WindowContext(BrowsingContext* aBrowsingContext, uint64_t aInnerWindowId,
uint64_t aOuterWindowId, bool aInProcess, FieldTuple&& aFields);
......
......@@ -501,8 +501,7 @@ already_AddRefed<nsDocShell> nsDocShell::Create(
// various methods via which nsDocLoader can be notified. Note that this
// holds an nsWeakPtr to |ds|, so it's ok.
rv = ds->AddProgressListener(ds, nsIWebProgress::NOTIFY_STATE_DOCUMENT |
nsIWebProgress::NOTIFY_STATE_NETWORK |
nsIWebProgress::NOTIFY_LOCATION);
nsIWebProgress::NOTIFY_STATE_NETWORK);
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
......@@ -1401,6 +1400,40 @@ void nsDocShell::GetParentCharset(const Encoding*& aCharset,
NS_IF_ADDREF(*aPrincipal = mParentCharsetPrincipal);
}
NS_IMETHODIMP
nsDocShell::GetHasMixedActiveContentLoaded(bool* aHasMixedActiveContentLoaded) {
RefPtr<Document> doc(GetDocument());
*aHasMixedActiveContentLoaded = doc && doc->GetHasMixedActiveContentLoaded();
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetHasMixedActiveContentBlocked(
bool* aHasMixedActiveContentBlocked) {
RefPtr<Document> doc(GetDocument());
*aHasMixedActiveContentBlocked =
doc && doc->GetHasMixedActiveContentBlocked();
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetHasMixedDisplayContentLoaded(
bool* aHasMixedDisplayContentLoaded) {
RefPtr<Document> doc(GetDocument());
*aHasMixedDisplayContentLoaded =
doc && doc->GetHasMixedDisplayContentLoaded();
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetHasMixedDisplayContentBlocked(
bool* aHasMixedDisplayContentBlocked) {
RefPtr<Document> doc(GetDocument());
*aHasMixedDisplayContentBlocked =
doc && doc->GetHasMixedDisplayContentBlocked();
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetHasTrackingContentBlocked(Promise** aPromise) {
MOZ_ASSERT(aPromise);
......@@ -1941,6 +1974,20 @@ nsDocShell::TabToTreeOwner(bool aForward, bool aForDocumentNavigation,
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetSecurityUI(nsISecureBrowserUI** aSecurityUI) {
NS_IF_ADDREF(*aSecurityUI = mSecurityUI);
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::SetSecurityUI(nsISecureBrowserUI* aSecurityUI) {
MOZ_ASSERT(!mIsBeingDestroyed);
mSecurityUI = aSecurityUI;
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetLoadURIDelegate(nsILoadURIDelegate** aLoadURIDelegate) {
nsCOMPtr<nsILoadURIDelegate> delegate = GetLoadURIDelegate();
......@@ -4301,6 +4348,9 @@ nsDocShell::Destroy() {
mChromeEventHandler = nullptr;
// required to break ref cycle
mSecurityUI = nullptr;
// Cancel any timers that were set for this docshell; this is needed
// to break the cycle between us and the timers.
CancelRefreshURITimers();
......@@ -5573,17 +5623,7 @@ nsDocShell::OnStateChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
NS_IMETHODIMP
nsDocShell::OnLocationChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
nsIURI* aURI, uint32_t aFlags) {
if (XRE_IsParentProcess()) {
// Since we've now changed Documents, notify the BrowsingContext that we've
// changed. Ideally we'd just let the BrowsingContext do this when it
// changes the current window global, but that happens before this and we
// have a lot of tests that depend on the specific ordering of messages.
if (!(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT)) {
GetBrowsingContext()
->Canonical()
->UpdateSecurityStateForLocationOrMixedContentChange();
}
}
MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)");
return NS_OK;
}
......
......@@ -1146,6 +1146,9 @@ class nsDocShell final : public nsDocLoader,
// Editor data, if this document is designMode or contentEditable.
mozilla::UniquePtr<nsDocShellEditorData> mEditorData;
// Secure browser UI object
nsCOMPtr<nsISecureBrowserUI> mSecurityUI;
// The URI we're currently loading. This is only relevant during the
// firing of a pagehide/unload. The caller of FirePageHideNotification()
// is responsible for setting it and unsetting it. It may be null if the
......
......@@ -353,6 +353,12 @@ interface nsIDocShell : nsIDocShellTreeItem
attribute nsILayoutHistoryState layoutHistoryState;
/**
* The SecureBrowserUI object for this docshell. This is set by XUL
* <browser> or nsWebBrowser for their root docshell.
*/
attribute nsISecureBrowserUI securityUI;
/**
* Object used to delegate URI loading to an upper context.
* Currently only set for GeckoView to allow handling of load requests
......@@ -460,6 +466,45 @@ interface nsIDocShell : nsIDocShellTreeItem
*/
readonly attribute boolean isInUnload;
/**
* This attribute determines whether Mixed Active Content is loaded on the
* document. When it is true, mixed active content was not blocked and has
* loaded (or is about to load) on the page. When it is false, mixed active content
* has not loaded on the page, either because there was no mixed active content
* requests on the page or such requests were blocked by nsMixedContentBlocker.
* This boolean is set to true in nsMixedContentBlocker if Mixed Active Content
* is allowed (either explicitly on the page by the user or when the about:config
* setting security.mixed_content.block_active_content is set to false).
*/
[infallible] readonly attribute boolean hasMixedActiveContentLoaded;
/**
* This attribute determines whether a document has Mixed Active Content
* that has been blocked from loading. When it is true, there is definitely
* mixed active content on a page that has been blocked by
* nsMixedContentBlocker. When it is false, there may or may not be mixed
* active content on a page, but if there is, it will load. Note that if the
* about:config setting security.mixed_content.block_active_content is set
* false, this boolean will be false, since blocking active content has been
* disabled.
*/
[infallible] readonly attribute boolean hasMixedActiveContentBlocked;
/**
* This attribute determines whether Mixed Display Content is loaded on the
* document. When it is true, mixed display content was not blocked and has
* loaded (or is about to load) on the page. Similar behavior to
* hasMixedActiveContentLoaded.
*/
[infallible] readonly attribute boolean hasMixedDisplayContentLoaded;
/**
* This attribute determines whether a document has Mixed Display Content
* that has been blocked from loading. Similar behavior to
* hasMixedActiveContentBlocked.
*/
[infallible] readonly attribute boolean hasMixedDisplayContentBlocked;
/**
* Disconnects this docshell's editor from its window, and stores the
* editor data in the open document's session history entry. This
......
......@@ -95,8 +95,7 @@ function step1B(aWebProgress, aRequest, aLocation, aFlags) {
"This page is an error page.");
ok(!(aWebProgress.QueryInterface(Ci.nsIDocShell)
.browsingContext
.secureBrowserUI.state &
.securityUI.state &
Ci.nsIWebProgressListener.STATE_IS_SECURE),
"This is not a secure page (1)");
......@@ -125,8 +124,7 @@ function step2B(aWebProgress, aRequest, aLocation, aFla