Backed out 4 changesets (bug 1646582) for Browser-chrome failures on nsIWebProgress.addProgressListener. CLOSED TREE

Backed out changeset 2111dd0d6dc0 (bug 1646582)
Backed out changeset e6c496c5a4b1 (bug 1646582)
Backed out changeset 49b4ae8c8be0 (bug 1646582)
Backed out changeset 9d42ec89240c (bug 1646582)
This commit is contained in:
Dorel Luca 2020-06-24 07:50:07 +03:00
Родитель e037947c1d
Коммит 90a64f0da1
31 изменённых файлов: 929 добавлений и 60 удалений

Просмотреть файл

@ -462,6 +462,20 @@ function addXULBrowserDecorations(browser) {
swapBrowser() {},
};
}
if (browser._remoteWebProgressManager == undefined) {
browser._remoteWebProgressManager = {
swapBrowser() {},
get progressListeners() {
return [];
},
};
}
if (browser._remoteWebProgress == undefined) {
browser._remoteWebProgress = {
addProgressListener() {},
removeProgressListener() {},
};
}
}
function tabLoaded(tab) {

Просмотреть файл

@ -32,6 +32,7 @@ const SWAPPED_BROWSER_STATE = [
"_characterSet",
"_contentPrincipal",
"_isSyntheticDocument",
"_innerWindowID",
];
/**
@ -102,6 +103,7 @@ function tunnelToInnerBrowser(outer, inner) {
inner._documentContentType = outer._documentContentType;
inner._characterSet = outer._characterSet;
inner._isSyntheticDocument = outer._isSyntheticDocument;
inner._innerWindowID = outer._innerWindowID;
inner._remoteWebNavigation._currentURI =
outer._remoteWebNavigation._currentURI;
// mozbrowser elements do not support the `contentPrincipal` property.

Просмотреть файл

@ -47,6 +47,16 @@ NS_IMETHODIMP BrowsingContextWebProgress::GetDOMWindow(
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP BrowsingContextWebProgress::GetDOMWindowID(
uint64_t* aDOMWindowID) {
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP BrowsingContextWebProgress::GetInnerDOMWindowID(
uint64_t* aInnerDOMWindowID) {
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP BrowsingContextWebProgress::GetIsTopLevel(bool* aIsTopLevel) {
*aIsTopLevel = true;
return NS_OK;

Просмотреть файл

@ -68,6 +68,14 @@ interface nsIBrowser : nsISupports
*/
readonly attribute boolean isRemoteBrowser;
/**
* The nsIWebProgress instance responsible for handling progress events
* from the content process.
*
* Will always be non-null when isRemoteBrowser is true.
*/
readonly attribute nsIWebProgress remoteWebProgressManager;
readonly attribute nsIPrincipal contentPrincipal;
readonly attribute nsIPrincipal contentPartitionedPrincipal;
readonly attribute nsIPrincipal contentBlockingAllowListPrincipal;
@ -130,6 +138,7 @@ interface nsIBrowser : nsISupports
* @param aCSP the content security policy of the new document
* @param aReferrerInfo the referrer info of the new document
* @param aIsSynthetic whether or not the document is synthetic
* @param aInnerWindowID the inner window ID of the document
* @param aHasRequestContextID whether or not the the request context has a
* value (true) or null should be used (false)
* @param aRequestContextID the request context ID
@ -146,6 +155,7 @@ interface nsIBrowser : nsISupports
in nsIContentSecurityPolicy aCSP,
in nsIReferrerInfo aReferrerInfo,
in boolean aIsSynthetic,
in uint64_t aInnerWindowID,
in boolean aHasRequestContextID,
in uint64_t aRequestContextID,
in AString aContentType);

Просмотреть файл

@ -3518,6 +3518,29 @@ NS_IMETHODIMP BrowserChild::OnStateChange(nsIWebProgress* aWebProgress,
MOZ_TRY(PrepareProgressListenerData(aWebProgress, aRequest, webProgressData,
requestData));
/*
* If
* 1) this is a document,
* 2) the document is top-level,
* 3) the document is completely loaded (STATE_STOP), and
* 4) this is the end of activity for the document
* (STATE_IS_WINDOW, STATE_IS_NETWORK),
* then record the elapsed time that it took to load.
*/
if (document && webProgressData->isTopLevel() &&
(aStateFlags & nsIWebProgressListener::STATE_STOP) &&
(aStateFlags & nsIWebProgressListener::STATE_IS_WINDOW) &&
(aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK)) {
RefPtr<nsDOMNavigationTiming> navigationTiming =
document->GetNavigationTiming();
if (navigationTiming) {
TimeDuration elapsedLoadTimeMS =
TimeStamp::Now() - navigationTiming->GetNavigationStartTimeStamp();
requestData.elapsedLoadTimeMS() =
Some(elapsedLoadTimeMS.ToMilliseconds());
}
}
if (webProgressData->isTopLevel()) {
stateChangeData.emplace();
@ -3747,6 +3770,17 @@ nsresult BrowserChild::PrepareProgressListenerData(
rv = aWebProgress->GetLoadType(&loadType);
NS_ENSURE_SUCCESS(rv, rv);
aWebProgressData->loadType() = loadType;
uint64_t outerDOMWindowID = 0;
uint64_t innerDOMWindowID = 0;
// The DOM Window ID getters here may throw if the inner or outer windows
// aren't created yet or are destroyed at the time we're making this call
// but that isn't fatal so ignore the exceptions here.
Unused << aWebProgress->GetDOMWindowID(&outerDOMWindowID);
aWebProgressData->outerDOMWindowID() = outerDOMWindowID;
Unused << aWebProgress->GetInnerDOMWindowID(&innerDOMWindowID);
aWebProgressData->innerDOMWindowID() = innerDOMWindowID;
}
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);

Просмотреть файл

@ -2581,14 +2581,17 @@ mozilla::ipc::IPCResult BrowserParent::RecvOnStateChange(
return IPC_OK();
}
nsCOMPtr<nsIBrowser> browser = GetBrowser();
if (!GetBrowsingContext()->GetWebProgress() || !browser) {
nsCOMPtr<nsIBrowser> browser;
nsCOMPtr<nsIWebProgress> manager;
nsCOMPtr<nsIWebProgressListener> managerAsListener;
if (!GetWebProgressListener(getter_AddRefs(browser), getter_AddRefs(manager),
getter_AddRefs(managerAsListener))) {
return IPC_OK();
}
nsCOMPtr<nsIWebProgress> webProgress;
nsCOMPtr<nsIRequest> request;
ReconstructWebProgressAndRequest(aWebProgressData, aRequestData,
ReconstructWebProgressAndRequest(manager, aWebProgressData, aRequestData,
getter_AddRefs(webProgress),
getter_AddRefs(request));
@ -2608,8 +2611,14 @@ mozilla::ipc::IPCResult BrowserParent::RecvOnStateChange(
"Unexpected WebProgressStateChangeData for non-top-level WebProgress");
}
GetBrowsingContext()->Top()->GetWebProgress()->OnStateChange(
webProgress, request, aStateFlags, aStatus);
Unused << managerAsListener->OnStateChange(webProgress, request, aStateFlags,
aStatus);
if (GetBrowsingContext()->Top()->GetWebProgress()) {
GetBrowsingContext()->Top()->GetWebProgress()->OnStateChange(
webProgress, request, aStateFlags, aStatus);
}
return IPC_OK();
}
@ -2622,20 +2631,30 @@ mozilla::ipc::IPCResult BrowserParent::RecvOnProgressChange(
return IPC_OK();
}
if (!GetBrowsingContext()->GetWebProgress()) {
nsCOMPtr<nsIBrowser> browser;
nsCOMPtr<nsIWebProgress> manager;
nsCOMPtr<nsIWebProgressListener> managerAsListener;
if (!GetWebProgressListener(getter_AddRefs(browser), getter_AddRefs(manager),
getter_AddRefs(managerAsListener))) {
return IPC_OK();
}
nsCOMPtr<nsIWebProgress> webProgress;
nsCOMPtr<nsIRequest> request;
ReconstructWebProgressAndRequest(aWebProgressData, aRequestData,
ReconstructWebProgressAndRequest(manager, aWebProgressData, aRequestData,
getter_AddRefs(webProgress),
getter_AddRefs(request));
GetBrowsingContext()->Top()->GetWebProgress()->OnProgressChange(
Unused << managerAsListener->OnProgressChange(
webProgress, request, aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress);
if (GetBrowsingContext()->Top()->GetWebProgress()) {
GetBrowsingContext()->Top()->GetWebProgress()->OnProgressChange(
webProgress, request, aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress);
}
return IPC_OK();
}
@ -2648,14 +2667,17 @@ mozilla::ipc::IPCResult BrowserParent::RecvOnLocationChange(
return IPC_OK();
}
nsCOMPtr<nsIBrowser> browser = GetBrowser();
if (!GetBrowsingContext()->GetWebProgress() || !browser) {
nsCOMPtr<nsIBrowser> browser;
nsCOMPtr<nsIWebProgress> manager;
nsCOMPtr<nsIWebProgressListener> managerAsListener;
if (!GetWebProgressListener(getter_AddRefs(browser), getter_AddRefs(manager),
getter_AddRefs(managerAsListener))) {
return IPC_OK();
}
nsCOMPtr<nsIWebProgress> webProgress;
nsCOMPtr<nsIRequest> request;
ReconstructWebProgressAndRequest(aWebProgressData, aRequestData,
ReconstructWebProgressAndRequest(manager, aWebProgressData, aRequestData,
getter_AddRefs(webProgress),
getter_AddRefs(request));
@ -2675,13 +2697,18 @@ mozilla::ipc::IPCResult BrowserParent::RecvOnLocationChange(
aLocationChangeData->contentPartitionedPrincipal(),
aLocationChangeData->csp(), aLocationChangeData->referrerInfo(),
aLocationChangeData->isSyntheticDocument(),
aWebProgressData->innerDOMWindowID(),
aLocationChangeData->requestContextID().isSome(),
aLocationChangeData->requestContextID().valueOr(0),
aLocationChangeData->contentType());
}
GetBrowsingContext()->Top()->GetWebProgress()->OnLocationChange(
webProgress, request, aLocation, aFlags);
Unused << managerAsListener->OnLocationChange(webProgress, request, aLocation,
aFlags);
if (GetBrowsingContext()->Top()->GetWebProgress()) {
GetBrowsingContext()->Top()->GetWebProgress()->OnLocationChange(
webProgress, request, aLocation, aFlags);
}
// 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
@ -2701,18 +2728,27 @@ mozilla::ipc::IPCResult BrowserParent::RecvOnStatusChange(
return IPC_OK();
}
if (!GetBrowsingContext()->GetWebProgress()) {
nsCOMPtr<nsIBrowser> browser;
nsCOMPtr<nsIWebProgress> manager;
nsCOMPtr<nsIWebProgressListener> managerAsListener;
if (!GetWebProgressListener(getter_AddRefs(browser), getter_AddRefs(manager),
getter_AddRefs(managerAsListener))) {
return IPC_OK();
}
nsCOMPtr<nsIWebProgress> webProgress;
nsCOMPtr<nsIRequest> request;
ReconstructWebProgressAndRequest(aWebProgressData, aRequestData,
ReconstructWebProgressAndRequest(manager, aWebProgressData, aRequestData,
getter_AddRefs(webProgress),
getter_AddRefs(request));
GetBrowsingContext()->Top()->GetWebProgress()->OnStatusChange(
webProgress, request, aStatus, aMessage.get());
Unused << managerAsListener->OnStatusChange(webProgress, request, aStatus,
aMessage.get());
if (GetBrowsingContext()->Top()->GetWebProgress()) {
GetBrowsingContext()->Top()->GetWebProgress()->OnStatusChange(
webProgress, request, aStatus, aMessage.get());
}
return IPC_OK();
}
@ -2735,6 +2771,8 @@ mozilla::ipc::IPCResult BrowserParent::RecvNotifyContentBlockingEvent(
const Maybe<
mozilla::ContentBlockingNotifier::StorageAccessPermissionGrantedReason>&
aReason) {
MOZ_ASSERT(aRequestData.elapsedLoadTimeMS().isNothing());
RefPtr<BrowsingContext> bc = GetBrowsingContext();
if (!bc || bc->IsDiscarded()) {
@ -2755,7 +2793,7 @@ mozilla::ipc::IPCResult BrowserParent::RecvNotifyContentBlockingEvent(
nsCOMPtr<nsIRequest> request = MakeAndAddRef<RemoteWebProgressRequest>(
aRequestData.requestURI(), aRequestData.originalRequestURI(),
aRequestData.matchedList());
aRequestData.matchedList(), aRequestData.elapsedLoadTimeMS());
wgp->NotifyContentBlockingEvent(aEvent, request, aBlocked, aTrackingOrigin,
aTrackingFullHashes, aReason);
@ -2775,7 +2813,13 @@ BrowserParent::RecvReportBlockedEmbedderNodeByClassifier() {
return IPC_OK();
}
already_AddRefed<nsIBrowser> BrowserParent::GetBrowser() {
bool BrowserParent::GetWebProgressListener(
nsIBrowser** aOutBrowser, nsIWebProgress** aOutManager,
nsIWebProgressListener** aOutListener) {
MOZ_ASSERT(aOutBrowser);
MOZ_ASSERT(aOutManager);
MOZ_ASSERT(aOutListener);
nsCOMPtr<nsIBrowser> browser;
RefPtr<Element> currentElement = mFrameElement;
@ -2793,11 +2837,31 @@ already_AddRefed<nsIBrowser> BrowserParent::GetBrowser() {
browsingContext ? browsingContext->GetEmbedderElement() : nullptr;
}
return browser.forget();
if (!browser) {
return false;
}
nsCOMPtr<nsIWebProgress> manager;
nsresult rv = browser->GetRemoteWebProgressManager(getter_AddRefs(manager));
if (NS_FAILED(rv)) {
return false;
}
nsCOMPtr<nsIWebProgressListener> listener = do_QueryInterface(manager);
if (!listener) {
// We are no longer remote so we cannot forward this event.
return false;
}
browser.forget(aOutBrowser);
manager.forget(aOutManager);
listener.forget(aOutListener);
return true;
}
void BrowserParent::ReconstructWebProgressAndRequest(
const Maybe<WebProgressData>& aWebProgressData,
nsIWebProgress* aManager, const Maybe<WebProgressData>& aWebProgressData,
const RequestData& aRequestData, nsIWebProgress** aOutWebProgress,
nsIRequest** aOutRequest) {
MOZ_DIAGNOSTIC_ASSERT(aOutWebProgress,
@ -2806,18 +2870,19 @@ void BrowserParent::ReconstructWebProgressAndRequest(
nsCOMPtr<nsIWebProgress> webProgress;
if (aWebProgressData) {
webProgress = new RemoteWebProgress(aWebProgressData->loadType(),
aWebProgressData->isLoadingDocument(),
aWebProgressData->isTopLevel());
webProgress = new RemoteWebProgress(
aManager, aWebProgressData->outerDOMWindowID(),
aWebProgressData->innerDOMWindowID(), aWebProgressData->loadType(),
aWebProgressData->isLoadingDocument(), aWebProgressData->isTopLevel());
} else {
webProgress = new RemoteWebProgress(0, false, false);
webProgress = new RemoteWebProgress(aManager, 0, 0, 0, false, false);
}
webProgress.forget(aOutWebProgress);
if (aRequestData.requestURI()) {
nsCOMPtr<nsIRequest> request = MakeAndAddRef<RemoteWebProgressRequest>(
aRequestData.requestURI(), aRequestData.originalRequestURI(),
aRequestData.matchedList());
aRequestData.matchedList(), aRequestData.elapsedLoadTimeMS());
request.forget(aOutRequest);
} else {
*aOutRequest = nullptr;

Просмотреть файл

@ -318,10 +318,12 @@ class BrowserParent final : public PBrowserParent,
mozilla::ipc::IPCResult RecvNavigationFinished();
already_AddRefed<nsIBrowser> GetBrowser();
bool GetWebProgressListener(nsIBrowser** aOutBrowser,
nsIWebProgress** aOutManager,
nsIWebProgressListener** aOutListener);
void ReconstructWebProgressAndRequest(
const Maybe<WebProgressData>& aWebProgressData,
nsIWebProgress* aManager, const Maybe<WebProgressData>& aWebProgressData,
const RequestData& aRequestData, nsIWebProgress** aOutWebProgress,
nsIRequest** aOutRequest);

Просмотреть файл

@ -106,6 +106,8 @@ struct WebProgressData
bool isTopLevel;
bool isLoadingDocument;
uint32_t loadType;
uint64_t outerDOMWindowID;
uint64_t innerDOMWindowID;
};
struct RequestData
@ -113,6 +115,12 @@ struct RequestData
nsIURI requestURI;
nsIURI originalRequestURI;
nsCString matchedList;
// The elapsedLoadTimeMS is only set when the request has finished loading.
// In other words, this field is set only during and |OnStateChange| event
// where |aStateFlags| contains |nsIWebProgressListener::STATE_STOP| and
// |nsIWebProgressListener::STATE_IS_NETWORK| and
// |nsIWebProgressListener::STATE_IS_WINDOW|, and the document is top level.
uint64_t? elapsedLoadTimeMS;
};
struct WebProgressStateChangeData

Просмотреть файл

@ -7,28 +7,74 @@
namespace mozilla {
namespace dom {
NS_IMPL_ADDREF(RemoteWebProgress)
NS_IMPL_RELEASE(RemoteWebProgress)
NS_IMPL_CYCLE_COLLECTION(RemoteWebProgress, mManager)
NS_INTERFACE_MAP_BEGIN(RemoteWebProgress)
NS_IMPL_CYCLE_COLLECTING_ADDREF(RemoteWebProgress)
NS_IMPL_CYCLE_COLLECTING_RELEASE(RemoteWebProgress)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(RemoteWebProgress)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY(nsIWebProgress)
NS_INTERFACE_MAP_ENTRY(nsIRemoteWebProgress)
NS_INTERFACE_MAP_END
NS_IMETHODIMP RemoteWebProgress::Init(nsIWebProgress* aManager,
bool aIsTopLevel) {
mManager = aManager;
mIsTopLevel = aIsTopLevel;
return NS_OK;
}
NS_IMETHODIMP RemoteWebProgress::Update(uint64_t aOuterDOMWindowID,
uint64_t aInnerDOMWindowID,
uint32_t aLoadType,
bool aIsLoadingDocument) {
mOuterDOMWindowID = aOuterDOMWindowID;
mInnerDOMWindowID = aInnerDOMWindowID;
mLoadType = aLoadType;
mIsLoadingDocument = aIsLoadingDocument;
return NS_OK;
}
NS_IMETHODIMP RemoteWebProgress::AddProgressListener(
nsIWebProgressListener* aListener, uint32_t aNotifyMask) {
return NS_ERROR_NOT_IMPLEMENTED;
if (mManager) {
return mManager->AddProgressListener(aListener, aNotifyMask);
} else {
NS_WARNING("RemoteWebProgres::mManager should not be null!");
}
return NS_OK;
}
NS_IMETHODIMP RemoteWebProgress::RemoveProgressListener(
nsIWebProgressListener* aListener) {
return NS_ERROR_NOT_IMPLEMENTED;
if (mManager) {
return mManager->RemoveProgressListener(aListener);
} else {
NS_WARNING("RemoteWebProgres::mManager should not be null!");
}
return NS_OK;
}
NS_IMETHODIMP RemoteWebProgress::GetDOMWindow(mozIDOMWindowProxy** aDOMWindow) {
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP RemoteWebProgress::GetDOMWindowID(uint64_t* aDOMWindowID) {
*aDOMWindowID = mOuterDOMWindowID;
return NS_OK;
}
NS_IMETHODIMP RemoteWebProgress::GetInnerDOMWindowID(
uint64_t* aInnerDOMWindowID) {
*aInnerDOMWindowID = mInnerDOMWindowID;
return NS_OK;
}
NS_IMETHODIMP RemoteWebProgress::GetIsTopLevel(bool* aIsTopLevel) {
NS_ENSURE_ARG_POINTER(aIsTopLevel);
*aIsTopLevel = mIsTopLevel;

Просмотреть файл

@ -5,29 +5,46 @@
#ifndef mozilla_dom_RemoteWebProgress_h
#define mozilla_dom_RemoteWebProgress_h
#include "nsIWebProgress.h"
#include "nsIRemoteWebProgress.h"
#include "nsCycleCollectionParticipant.h"
#include "nsCOMPtr.h"
namespace mozilla {
namespace dom {
class RemoteWebProgress final : public nsIWebProgress {
class RemoteWebProgress final : public nsIRemoteWebProgress {
public:
NS_DECL_ISUPPORTS
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(RemoteWebProgress)
NS_DECL_NSIWEBPROGRESS
NS_DECL_NSIREMOTEWEBPROGRESS
RemoteWebProgress()
: mLoadType(0), mIsLoadingDocument(false), mIsTopLevel(false) {}
: mManager(nullptr),
mOuterDOMWindowID(0),
mInnerDOMWindowID(0),
mLoadType(0),
mIsLoadingDocument(false),
mIsTopLevel(false) {}
RemoteWebProgress(uint32_t aLoadType, bool aIsLoadingDocument,
bool aIsTopLevel)
: mLoadType(aLoadType),
RemoteWebProgress(nsIWebProgress* aManager, uint64_t aOuterDOMWindowID,
uint64_t aInnerDOMWindowID, uint32_t aLoadType,
bool aIsLoadingDocument, bool aIsTopLevel)
: mManager(aManager),
mOuterDOMWindowID(aOuterDOMWindowID),
mInnerDOMWindowID(aInnerDOMWindowID),
mLoadType(aLoadType),
mIsLoadingDocument(aIsLoadingDocument),
mIsTopLevel(aIsTopLevel) {}
private:
virtual ~RemoteWebProgress() = default;
nsCOMPtr<nsIWebProgress> mManager;
uint64_t mOuterDOMWindowID;
uint64_t mInnerDOMWindowID;
uint32_t mLoadType;
bool mIsLoadingDocument;
bool mIsTopLevel;

Просмотреть файл

@ -10,7 +10,26 @@ namespace mozilla {
namespace dom {
NS_IMPL_ISUPPORTS(RemoteWebProgressRequest, nsIRequest, nsIChannel,
nsIClassifiedChannel)
nsIClassifiedChannel, nsIRemoteWebProgressRequest)
NS_IMETHODIMP RemoteWebProgressRequest::Init(nsIURI* aURI,
nsIURI* aOriginalURI) {
mURI = aURI;
mOriginalURI = aOriginalURI;
return NS_OK;
}
NS_IMETHODIMP RemoteWebProgressRequest::GetElapsedLoadTimeMS(
uint64_t* aElapsedLoadTimeMS) {
NS_ENSURE_ARG_POINTER(aElapsedLoadTimeMS);
if (mMaybeElapsedLoadTimeMS) {
*aElapsedLoadTimeMS = *mMaybeElapsedLoadTimeMS;
return NS_OK;
}
*aElapsedLoadTimeMS = 0;
return NS_ERROR_NOT_AVAILABLE;
}
// nsIChannel methods

Просмотреть файл

@ -7,21 +7,31 @@
#include "nsIChannel.h"
#include "nsIClassifiedChannel.h"
#include "nsIRemoteWebProgressRequest.h"
namespace mozilla {
namespace dom {
class RemoteWebProgressRequest final : public nsIChannel,
class RemoteWebProgressRequest final : public nsIRemoteWebProgressRequest,
public nsIChannel,
public nsIClassifiedChannel {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIREMOTEWEBPROGRESSREQUEST
NS_DECL_NSICHANNEL
NS_DECL_NSICLASSIFIEDCHANNEL
NS_DECL_NSIREQUEST
RemoteWebProgressRequest()
: mURI(nullptr), mOriginalURI(nullptr), mMatchedList(VoidCString()) {}
RemoteWebProgressRequest(nsIURI* aURI, nsIURI* aOriginalURI,
const nsACString& aMatchedList)
: mURI(aURI), mOriginalURI(aOriginalURI), mMatchedList(aMatchedList) {}
const nsACString& aMatchedList,
const Maybe<uint64_t>& aMaybeElapsedLoadTimeMS)
: mURI(aURI),
mOriginalURI(aOriginalURI),
mMatchedList(aMatchedList),
mMaybeElapsedLoadTimeMS(aMaybeElapsedLoadTimeMS) {}
protected:
~RemoteWebProgressRequest() = default;
@ -30,6 +40,13 @@ class RemoteWebProgressRequest final : public nsIChannel,
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIURI> mOriginalURI;
nsCString mMatchedList;
// This field is only Some(...) when the RemoteWebProgressRequest
// is created at a time that the document whose progress is being
// described by this request is top level and its status changes
// from loading to completely loaded.
// See BrowserChild::OnStateChange.
Maybe<uint64_t> mMaybeElapsedLoadTimeMS;
};
} // namespace dom

Просмотреть файл

@ -472,14 +472,37 @@ void WindowGlobalParent::NotifyContentBlockingEvent(
// Notify the OnContentBlockingEvent if necessary.
if (event) {
if (!GetBrowsingContext()->GetWebProgress()) {
// Get the browser parent from the manager directly since the content
// blocking event could happen in the early stage of loading, i.e.
// accessing cookies for the http header. At this stage, the actor is
// not ready, so we would get a nullptr from GetBrowserParent(). But,
// we can actually get it from the manager.
RefPtr<BrowserParent> browserParent =
static_cast<BrowserParent*>(Manager());
if (NS_WARN_IF(!browserParent)) {
return;
}
nsCOMPtr<nsIBrowser> browser;
nsCOMPtr<nsIWebProgress> manager;
nsCOMPtr<nsIWebProgressListener> managerAsListener;
if (!browserParent->GetWebProgressListener(
getter_AddRefs(browser), getter_AddRefs(manager),
getter_AddRefs(managerAsListener))) {
return;
}
nsCOMPtr<nsIWebProgress> webProgress =
new RemoteWebProgress(0, false, BrowsingContext()->IsTopContent());
GetBrowsingContext()->Top()->GetWebProgress()->OnContentBlockingEvent(
webProgress, aRequest, event.value());
new RemoteWebProgress(manager, OuterWindowId(), InnerWindowId(), 0,
false, BrowsingContext()->IsTopContent());
Unused << managerAsListener->OnContentBlockingEvent(webProgress, aRequest,
event.value());
if (GetBrowsingContext()->Top()->GetWebProgress()) {
GetBrowsingContext()->Top()->GetWebProgress()->OnContentBlockingEvent(
webProgress, aRequest, event.value());
}
}
}

20
dom/ipc/components.conf Normal file
Просмотреть файл

@ -0,0 +1,20 @@
# 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/.
Classes = [
{
'name': 'RemoteWebProgress',
'cid': 'a87eb91c-2a5c-11e9-ac91-d027ecb1fb94',
'contract_ids': ['@mozilla.org/dom/remote-web-progress;1'],
'type': 'mozilla::dom::RemoteWebProgress',
'headers': ['mozilla/dom/RemoteWebProgress.h'],
},
{
'name': 'RemoteWebProgressRequest',
'cid': 'eec2e27d-dc1d-4ab3-bed4-63536bd2a21e',
'contract_ids': ['@mozilla.org/dom/remote-web-progress-request;1'],
'type': 'mozilla::dom::RemoteWebProgressRequest',
'headers': ['mozilla/dom/RemoteWebProgressRequest.h'],
},
]

Просмотреть файл

@ -11,10 +11,16 @@ XPIDL_SOURCES += [
'nsIContentChild.idl',
'nsIContentParent.idl',
'nsIHangReport.idl',
'nsIRemoteWebProgress.idl',
'nsIRemoteWebProgressRequest.idl',
]
XPIDL_MODULE = 'dom'
XPCOM_MANIFESTS += [
'components.conf',
]
EXTRA_JS_MODULES += [
'ManifestMessagesChild.jsm',
]

Просмотреть файл

@ -0,0 +1,30 @@
/* 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/. */
#include "nsIWebProgress.idl"
[scriptable, uuid(2104bfce-bbbe-4111-aa29-cd7c91d1023b)]
interface nsIRemoteWebProgress : nsIWebProgress {
/**
* Initialize the web progress.
*
* @param aManager The RemoteWebProgressManager for this remote nsIWebProgress.
* @param aIsTopLevel Whether or not this is a top-level web progress.
*/
void init(in nsIWebProgress aManager,
in boolean aIsTopLevel);
/**
* Update the RemoteWebProgress with values from the content process.
*
* @param aOuterWindowID The outer window ID.
* @param aInnerWindowID The inner window ID.
* @param aLoadType The load type.
* @param aIsLoadingDocument Whether or not a document is being loaded.
*/
void update(in uint64_t aOuterWindowID,
in uint64_t aInnerWindowID,
in uint32_t aLoadType,
in boolean aIsLoadingDocument);
};

Просмотреть файл

@ -0,0 +1,20 @@
/* 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/. */
#include "nsISupports.idl"
interface nsIURI;
[scriptable, uuid(e14ff4c2-7e26-4748-8755-dfd074b9c746)]
interface nsIRemoteWebProgressRequest : nsISupports
{
void init(in nsIURI aURI, in nsIURI aOriginalURI);
// This field is available to users in |OnStateChange| methods only
// when the document whose progress is being described by this progress
// request is top level and its status has just changed from loading to
// completely loaded; for invocations of |OnStateChange| before or after
// that transition, this field will throw |NS_ERROR_UNAVAILABLE|.
readonly attribute uint64_t elapsedLoadTimeMS;
};

Просмотреть файл

@ -17,6 +17,9 @@ skip-if = !fission || !crashreporter || verify
skip-if = true || !e10s # This is an e10s only probe, but the test is currently broken. See Bug 1449991
[browser_cancel_content_js.js]
skip-if = !e10s
[browser_ElapsedTime.js]
support-files = elapsed_time.sjs
skip-if = (debug && os == "linux" && os_version == "18.04") || (!debug && os == "win") #Bug 1591344
[browser_bug1646088.js]
support-files = file_dummy.html
skip-if = !e10s

Просмотреть файл

@ -0,0 +1,68 @@
"use strict";
/*
* Synchronize DELAY_MS with DELAY_MS from elapsed_time.sjs
*/
const DELAY_MS = 200;
const SLOW_PAGE =
getRootDirectory(gTestPath).replace(
"chrome://mochitests/content",
"https://example.com"
) + "elapsed_time.sjs";
add_task(async function testLongElapsedTime() {
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:blank" },
async function(tabBrowser) {
const flags = Ci.nsIWebProgress.NOTIFY_STATE_NETWORK;
let listener;
let stateChangeWaiter = new Promise(resolve => {
listener = {
QueryInterface: ChromeUtils.generateQI([
Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference,
]),
onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
if (!aWebProgress.isTopLevel) {
return;
}
const isTopLevel = aWebProgress.isTopLevel;
const isStop = aStateFlags & Ci.nsIWebProgressListener.STATE_STOP;
const isNetwork =
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK;
const isWindow =
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW;
const isLoadingDocument = aWebProgress.isLoadingDocument;
if (
isTopLevel &&
isStop &&
isWindow &&
isNetwork &&
!isLoadingDocument
) {
aRequest.QueryInterface(Ci.nsIRemoteWebProgressRequest);
if (aRequest.elapsedLoadTimeMS >= DELAY_MS) {
resolve(true);
}
}
},
};
});
tabBrowser.addProgressListener(listener, flags);
BrowserTestUtils.loadURI(tabBrowser, SLOW_PAGE);
await BrowserTestUtils.browserLoaded(tabBrowser);
let pass = await stateChangeWaiter;
tabBrowser.removeProgressListener(listener);
ok(
pass,
"Bug 1559657: Check that the elapsedLoadTimeMS in RemoteWebProgress meets expectations."
);
}
);
});

Просмотреть файл

@ -0,0 +1,31 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
const DELAY_MS = 200;
const HTML = `<!DOCTYPE HTML>
<html dir="ltr" xml:lang="en-US" lang="en-US">
<head>
<meta charset="utf8">
</head>
<body>
</body>
</html>`;
/*
* Keep timer as a global so that it is not GC'd
* between the time that handleRequest() completes
* and it expires.
*/
var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
function handleRequest(req, resp) {
resp.processAsync();
resp.setHeader("Cache-Control", "no-cache", false);
resp.setHeader("Content-Type", "text/html;charset=utf-8", false);
resp.write(HTML);
timer.init(() => {
resp.write("");
resp.finish();
}, DELAY_MS, Ci.nsITimer.TYPE_ONE_SHOT);
}

Просмотреть файл

@ -1374,8 +1374,7 @@ DocumentLoadListener::RedirectToRealChannel(
RedirectChannelRegistrar::GetOrCreate();
MOZ_ASSERT(registrar);
mRedirectChannelId = nsContentUtils::GenerateLoadIdentifier();
MOZ_ALWAYS_SUCCEEDS(
registrar->RegisterChannel(mChannel, mRedirectChannelId));
MOZ_ALWAYS_SUCCEEDS(registrar->RegisterChannel(mChannel, mRedirectChannelId));
if (aDestinationProcess) {
dom::ContentParent* cp =
@ -1931,6 +1930,70 @@ auto DocumentLoadListener::AttachStreamFilter(base::ProcessId aChildProcessId)
return request->mPromise;
}
already_AddRefed<nsIBrowser> DocumentLoadListener::GetBrowser() {
CanonicalBrowsingContext* bc = GetBrowsingContext();
if (!bc || !bc->IsTopContent()) {
return nullptr;
}
nsCOMPtr<nsIBrowser> browser;
RefPtr<Element> currentElement = bc->GetEmbedderElement();
// In Responsive Design Mode, mFrameElement will be the <iframe mozbrowser>,
// but we want the <xul:browser> that it is embedded in.
while (currentElement) {
browser = currentElement->AsBrowser();
if (browser) {
break;
}
BrowsingContext* browsingContext =
currentElement->OwnerDoc()->GetBrowsingContext();
currentElement =
browsingContext ? browsingContext->GetEmbedderElement() : nullptr;
}
return browser.forget();
}
already_AddRefed<nsIWebProgressListener>
DocumentLoadListener::GetRemoteWebProgressListener(
nsIWebProgress** aWebProgress, nsIRequest** aRequest) {
nsCOMPtr<nsIBrowser> browser = GetBrowser();
if (!browser) {
return nullptr;
}
nsCOMPtr<nsIWebProgress> manager;
nsresult rv = browser->GetRemoteWebProgressManager(getter_AddRefs(manager));
if (NS_FAILED(rv)) {
return nullptr;
}
nsCOMPtr<nsIWebProgressListener> listener = do_QueryInterface(manager);
if (!listener) {
// We are no longer remote so we cannot forward this event.
return nullptr;
}
nsCOMPtr<nsILoadInfo> loadInfo = mChannel->LoadInfo();
nsCOMPtr<nsIWebProgress> webProgress = new RemoteWebProgress(
manager, loadInfo->GetOuterWindowID(),
/* aInnerDOMWindowID = */ 0, mLoadStateLoadType, true, true);
nsCOMPtr<nsIURI> uri, originalUri;
mChannel->GetURI(getter_AddRefs(uri));
mChannel->GetOriginalURI(getter_AddRefs(originalUri));
nsCString matchedList;
nsCOMPtr<nsIRequest> request = MakeAndAddRef<RemoteWebProgressRequest>(
uri, originalUri, matchedList, Nothing());
webProgress.forget(aWebProgress);
request.forget(aRequest);
return listener.forget();
}
NS_IMETHODIMP DocumentLoadListener::OnProgress(nsIRequest* aRequest,
int64_t aProgress,
int64_t aProgressMax) {
@ -1940,17 +2003,25 @@ NS_IMETHODIMP DocumentLoadListener::OnProgress(nsIRequest* aRequest,
NS_IMETHODIMP DocumentLoadListener::OnStatus(nsIRequest* aRequest,
nsresult aStatus,
const char16_t* aStatusArg) {
nsCOMPtr<nsIChannel> channel = mChannel;
nsCOMPtr<nsIWebProgress> webProgress =
new RemoteWebProgress(mLoadStateLoadType, true, true);
nsCOMPtr<nsIWebProgress> webProgress;
nsCOMPtr<nsIRequest> request;
nsCOMPtr<nsIWebProgressListener> listener = GetRemoteWebProgressListener(
getter_AddRefs(webProgress), getter_AddRefs(request));
if (!listener) {
return NS_OK;
}
RefPtr<CanonicalBrowsingContext> ctx = GetBrowsingContext();
const nsString message(aStatusArg);
NS_DispatchToMainThread(
NS_NewRunnableFunction("DocumentLoadListener::FireStateChange", [=]() {
Unused << listener->OnStatusChange(webProgress, request, aStatus,
message.get());
if (ctx && ctx->Top()->GetWebProgress()) {
ctx->Top()->GetWebProgress()->OnStatusChange(webProgress, channel,
ctx->Top()->GetWebProgress()->OnStatusChange(webProgress, request,
aStatus, message.get());
}
}));

Просмотреть файл

@ -177,6 +177,10 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
nsIChannel* GetChannel() const { return mChannel; }
already_AddRefed<nsIBrowser> GetBrowser();
already_AddRefed<nsIWebProgressListener> GetRemoteWebProgressListener(
nsIWebProgress** aWebProgress, nsIRequest** aRequest);
uint32_t GetRedirectChannelId() const { return mRedirectChannelId; }
nsresult ReportSecurityMessage(const nsAString& aMessageTag,

Просмотреть файл

@ -51,6 +51,57 @@ nsSecureBrowserUI::GetState(uint32_t* aState) {
return NS_OK;
}
static bool GetWebProgressListener(CanonicalBrowsingContext* aBrowsingContext,
nsIBrowser** aOutBrowser,
nsIWebProgress** aOutManager,
nsIWebProgressListener** aOutListener) {
MOZ_ASSERT(aOutBrowser);
MOZ_ASSERT(aOutManager);
MOZ_ASSERT(aOutListener);
nsCOMPtr<nsIBrowser> browser;
RefPtr<Element> currentElement = aBrowsingContext->GetEmbedderElement();
// In Responsive Design Mode, mFrameElement will be the <iframe mozbrowser>,
// but we want the <xul:browser> that it is embedded in.
while (currentElement) {
browser = currentElement->AsBrowser();
if (browser) {
break;
}
BrowsingContext* browsingContext =
currentElement->OwnerDoc()->GetBrowsingContext();
currentElement =
browsingContext ? browsingContext->GetEmbedderElement() : nullptr;
}
if (!browser) {
return false;
}
nsCOMPtr<nsIWebProgress> manager;
nsresult rv = browser->GetRemoteWebProgressManager(getter_AddRefs(manager));
if (NS_FAILED(rv)) {
browser.forget(aOutBrowser);
return true;
}
nsCOMPtr<nsIWebProgressListener> listener = do_QueryInterface(manager);
if (!listener) {
// We are no longer remote so we cannot forward this event.
browser.forget(aOutBrowser);
manager.forget(aOutManager);
return true;
}
browser.forget(aOutBrowser);
manager.forget(aOutManager);
listener.forget(aOutListener);
return true;
}
void nsSecureBrowserUI::UpdateForLocationOrMixedContentChange() {
// Our BrowsingContext either has a new WindowGlobalParent, or the
// existing one has mutated its security state.
@ -110,6 +161,26 @@ void nsSecureBrowserUI::UpdateForLocationOrMixedContentChange() {
return;
}
// This is a bit painful, as we need to do different things for
// in-process docshells vs OOP ones.
// Ideally we'd just call a function on 'browser' which would
// handle sending an event to all listeners, and we wouldn't
// need to bother with onSecurityChange.
nsCOMPtr<nsIBrowser> browser;
nsCOMPtr<nsIWebProgress> manager;
nsCOMPtr<nsIWebProgressListener> managerAsListener;
if (!GetWebProgressListener(ctx, getter_AddRefs(browser),
getter_AddRefs(manager),
getter_AddRefs(managerAsListener))) {
return;
}
// Do we need to construct a fake webprogress and request instance?
// Should we split this API out of nsIWebProgressListener to avoid
// that?
if (managerAsListener) {
Unused << managerAsListener->OnSecurityChange(nullptr, nullptr, mState);
}
if (ctx->GetDocShell()) {
nsDocShell* nativeDocShell = nsDocShell::Cast(ctx->GetDocShell());
nativeDocShell->nsDocLoader::OnSecurityChange(nullptr, mState);

Просмотреть файл

@ -284,8 +284,14 @@ NS_IMETHODIMP TabListener::OnStateChange(nsIWebProgress* aWebProgress,
return NS_OK;
}
nsCOMPtr<nsIWebProgress> webProgress = do_QueryInterface(mDocShell);
if (webProgress != aWebProgress) {
// The DOM Window ID getter here may throw if the inner or outer windows
// aren't created yet or are destroyed at the time we're making this call
// but that isn't fatal so ignore the exceptions here.
uint64_t DOMWindowID = 0;
Unused << aWebProgress->GetDOMWindowID(&DOMWindowID);
nsCOMPtr<nsPIDOMWindowOuter> window = do_GetInterface(mDocShell);
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
if (DOMWindowID != window->WindowID()) {
return NS_OK;
}

Просмотреть файл

@ -71,6 +71,20 @@ nsBrowserStatusFilter::GetDOMWindow(mozIDOMWindowProxy** aResult) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsBrowserStatusFilter::GetDOMWindowID(uint64_t* aResult) {
*aResult = 0;
MOZ_ASSERT_UNREACHABLE("nsBrowserStatusFilter::GetDOMWindowID");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsBrowserStatusFilter::GetInnerDOMWindowID(uint64_t* aResult) {
*aResult = 0;
MOZ_ASSERT_UNREACHABLE("nsBrowserStatusFilter::GetInnerDOMWindowID");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsBrowserStatusFilter::GetIsTopLevel(bool* aIsTopLevel) {
*aIsTopLevel = false;

Просмотреть файл

@ -230,10 +230,14 @@
this._fastFind = null;
this._innerWindowID = null;
this._lastSearchString = null;
this._remoteWebNavigation = null;
this._remoteWebProgress = null;
this._characterSet = "";
this._mayEnableCharacterEncodingMenu = null;
@ -581,7 +585,17 @@
}
get innerWindowID() {
return this.browsingContext?.currentWindowGlobal?.innerWindowId || null;
if (this.isRemoteBrowser) {
return this._innerWindowID;
}
try {
return this.contentWindow.windowUtils.currentInnerWindowID;
} catch (e) {
if (e.result != Cr.NS_ERROR_NOT_AVAILABLE) {
throw e;
}
return null;
}
}
get browsingContext() {
@ -1062,7 +1076,6 @@
construct() {
elementsToDestroyOnUnload.add(this);
let wasRemote = !!this._remoteWebNavigation;
this.resetFields();
this.mInitialized = true;
if (this.isRemoteBrowser) {
@ -1084,8 +1097,22 @@
// we should re-evaluate the CSP here.
this._csp = null;
if (!wasRemote) {
// If we weren't remote, then we're transitioning from local to
let jsm = "resource://gre/modules/RemoteWebProgress.jsm";
let { RemoteWebProgressManager } = ChromeUtils.import(jsm, {});
let oldManager = this._remoteWebProgressManager;
this._remoteWebProgressManager = new RemoteWebProgressManager(this);
if (oldManager) {
// We're transitioning from one remote type to another. This means that
// the RemoteWebProgress listener is listening to the old message manager,
// and needs to be pointed at the new one.
this._remoteWebProgressManager.swapListeners(oldManager);
}
this._remoteWebProgress = this._remoteWebProgressManager.topLevelWebProgress;
if (!oldManager) {
// If we didn't have a manager, then we're transitioning from local to
// remote. Add all listeners from the previous <browser> to the new
// RemoteWebProgress.
this.restoreProgressListeners();
@ -1138,7 +1165,13 @@
} catch (e) {}
if (!this.isRemoteBrowser) {
// If we've transitioned from remote to non-remote, we no longer need
// our RemoteWebProgress or its associated manager, but we'll need to
// add the progress listeners to the new non-remote WebProgress.
this._remoteWebProgressManager = null;
this._remoteWebProgress = null;
this.restoreProgressListeners();
this.addEventListener("pagehide", this.onPageHide, true);
}
}
@ -1176,6 +1209,10 @@
}
}
get remoteWebProgressManager() {
return this._remoteWebProgressManager;
}
updateForStateChange(aCharset, aDocumentURI, aContentType) {
if (this.isRemoteBrowser && this.messageManager) {
if (aCharset != null) {
@ -1211,6 +1248,7 @@
aCSP,
aReferrerInfo,
aIsSynthetic,
aInnerWindowID,
aHaveRequestContextID,
aRequestContextID,
aContentType
@ -1233,6 +1271,7 @@
this._csp = aCSP;
this._referrerInfo = aReferrerInfo;
this._isSyntheticDocument = aIsSynthetic;
this._innerWindowID = aInnerWindowID;
this._contentRequestContextID = aHaveRequestContextID
? aRequestContextID
: null;
@ -1613,7 +1652,10 @@
fieldsToSwap.push(
...[
"_remoteWebNavigation",
"_remoteWebProgressManager",
"_remoteWebProgress",
"_remoteFinder",
"_securityUI",
"_documentURI",
"_documentContentType",
"_characterSet",
@ -1622,6 +1664,7 @@
"_contentPrincipal",
"_contentPartitionedPrincipal",
"_isSyntheticDocument",
"_innerWindowID",
]
);
}
@ -1659,6 +1702,14 @@
this._remoteWebNavigation.swapBrowser(this);
aOtherBrowser._remoteWebNavigation.swapBrowser(aOtherBrowser);
if (
this._remoteWebProgressManager &&
aOtherBrowser._remoteWebProgressManager
) {
this._remoteWebProgressManager.swapBrowser(this);
aOtherBrowser._remoteWebProgressManager.swapBrowser(aOtherBrowser);
}
if (this._remoteFinder) {
this._remoteFinder.swapBrowser(this);
}

Просмотреть файл

@ -0,0 +1,164 @@
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
// 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/.
var EXPORTED_SYMBOLS = ["RemoteWebProgressManager"];
const RemoteWebProgress = Components.Constructor(
"@mozilla.org/dom/remote-web-progress;1",
"nsIRemoteWebProgress",
"init"
);
class RemoteWebProgressManager {
constructor(aBrowser) {
this._topLevelWebProgress = new RemoteWebProgress(
this.QueryInterface(Ci.nsIWebProgress),
/* aIsTopLevel = */ true
);
this._progressListeners = [];
this.swapBrowser(aBrowser);
}
swapBrowser(aBrowser) {
this._browser = aBrowser;
}
swapListeners(aOtherRemoteWebProgressManager) {
let temp = aOtherRemoteWebProgressManager.progressListeners;
aOtherRemoteWebProgressManager._progressListeners = this._progressListeners;
this._progressListeners = temp;
}
get progressListeners() {
return this._progressListeners;
}
get topLevelWebProgress() {
return this._topLevelWebProgress;
}
addProgressListener(aListener, aNotifyMask) {
let listener = aListener.QueryInterface(Ci.nsIWebProgressListener);
this._progressListeners.push({
listener,
mask: aNotifyMask || Ci.nsIWebProgress.NOTIFY_ALL,
});
}
removeProgressListener(aListener) {
this._progressListeners = this._progressListeners.filter(
l => l.listener != aListener
);
}
setCurrentURI(aURI) {
// This function is simpler than nsDocShell::SetCurrentURI since
// it doesn't have to deal with child docshells.
let remoteWebNav = this._browser._remoteWebNavigationImpl;
remoteWebNav._currentURI = aURI;
let webProgress = this.topLevelWebProgress;
for (let { listener, mask } of this._progressListeners) {
if (mask & Ci.nsIWebProgress.NOTIFY_LOCATION) {
listener.onLocationChange(webProgress, null, aURI);
}
}
}
_callProgressListeners(type, methodName, ...args) {
for (let { listener, mask } of this._progressListeners) {
if (mask & type && listener[methodName]) {
try {
listener[methodName](...args);
} catch (ex) {
if (ex.result != Cr.NS_ERROR_XPC_JSOBJECT_HAS_NO_FUNCTION_NAMED) {
Cu.reportError(
`RemoteWebProgress failed to call ${methodName}: ${ex}`
);
}
}
}
}
}
onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
this._callProgressListeners(
Ci.nsIWebProgress.NOTIFY_STATE_ALL,
"onStateChange",
aWebProgress,
aRequest,
aStateFlags,
aStatus
);
}
onProgressChange(
aWebProgress,
aRequest,
aCurSelfProgress,
aMaxSelfProgress,
aCurTotalProgress,
aMaxTotalProgress
) {
this._callProgressListeners(
Ci.nsIWebProgress.NOTIFY_PROGRESS,
"onProgressChange",
aWebProgress,
aRequest,
aCurSelfProgress,
aMaxSelfProgress,
aCurTotalProgress,
aMaxTotalProgress
);
}
onLocationChange(aWebProgress, aRequest, aLocation, aFlags) {
this._callProgressListeners(
Ci.nsIWebProgress.NOTIFY_LOCATION,
"onLocationChange",
aWebProgress,
aRequest,
aLocation,
aFlags
);
}
onStatusChange(aWebProgress, aRequest, aStatus, aMessage) {
this._callProgressListeners(
Ci.nsIWebProgress.NOTIFY_STATUS,
"onStatusChange",
aWebProgress,
aRequest,
aStatus,
aMessage
);
}
onSecurityChange(aWebProgress, aRequest, aState) {
this._callProgressListeners(
Ci.nsIWebProgress.NOTIFY_SECURITY,
"onSecurityChange",
aWebProgress,
aRequest,
aState
);
}
onContentBlockingEvent(aWebProgress, aRequest, aEvent) {
this._callProgressListeners(
Ci.nsIWebProgress.NOTIFY_CONTENT_BLOCKING,
"onContentBlockingEvent",
aWebProgress,
aRequest,
aEvent
);
}
}
RemoteWebProgressManager.prototype.QueryInterface = ChromeUtils.generateQI([
"nsIWebProgress",
"nsIWebProgressListener",
]);

Просмотреть файл

@ -117,6 +117,9 @@ with Files('PrivateBrowsingUtils.jsm'):
with Files('Promise*.jsm'):
BUG_COMPONENT = ('Toolkit', 'Async Tooling')
with Files('RemoteWebProgress.jsm'):
BUG_COMPONENT = ('Core', 'DOM: Navigation')
with Files('ResponsivenessMonitor.jsm'):
BUG_COMPONENT = ('Firefox', 'Migration')
@ -206,6 +209,7 @@ EXTRA_JS_MODULES += [
'PromiseUtils.jsm',
'Region.jsm',
'RemotePageAccessManager.jsm',
'RemoteWebProgress.jsm',
'ResetProfile.jsm',
'ResponsivenessMonitor.jsm',
'ServiceRequest.jsm',

Просмотреть файл

@ -175,6 +175,7 @@
"remote-settings.js": ["RemoteSettings", "jexlFilterFunc", "remoteSettingsBroadcastHandler"],
"RemotePageManagerChild.jsm": ["ChildMessagePort"],
"RemotePageManagerParent.jsm": ["RemotePages", "RemotePageManager"],
"RemoteWebProgress.jsm": ["RemoteWebProgressManager"],
"resource.js": ["AsyncResource", "Resource"],
"resource://services-common/utils.js": ["CommonUtils"],
"resource://services-crypto/utils.js": ["CryptoUtils"],

Просмотреть файл

@ -980,6 +980,42 @@ nsDocLoader::GetDOMWindow(mozIDOMWindowProxy** aResult) {
return CallGetInterface(this, aResult);
}
NS_IMETHODIMP
nsDocLoader::GetDOMWindowID(uint64_t* aResult) {
*aResult = 0;
nsCOMPtr<mozIDOMWindowProxy> window;
nsresult rv = GetDOMWindow(getter_AddRefs(window));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsPIDOMWindowOuter> piwindow = nsPIDOMWindowOuter::From(window);
NS_ENSURE_STATE(piwindow);
*aResult = piwindow->WindowID();
return NS_OK;
}
NS_IMETHODIMP
nsDocLoader::GetInnerDOMWindowID(uint64_t* aResult) {
*aResult = 0;
nsCOMPtr<mozIDOMWindowProxy> window;
nsresult rv = GetDOMWindow(getter_AddRefs(window));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsPIDOMWindowOuter> outer = nsPIDOMWindowOuter::From(window);
NS_ENSURE_STATE(outer);
nsPIDOMWindowInner* inner = outer->GetCurrentInnerWindow();
if (!inner) {
// If we don't have an inner window, return 0.
return NS_OK;
}
*aResult = inner->WindowID();
return NS_OK;
}
NS_IMETHODIMP
nsDocLoader::GetIsTopLevel(bool* aResult) {
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(this);

Просмотреть файл

@ -137,6 +137,8 @@ interface nsIWebProgress : nsISupports
* Indicates that there is no associated DOM window.
*/
readonly attribute mozIDOMWindowProxy DOMWindow;
readonly attribute uint64_t DOMWindowID;
readonly attribute uint64_t innerDOMWindowID;
/**
* Indicates whether DOMWindow.top == DOMWindow.