Bug 1696158 - Move CanSavePresentation to the parent process. Notify parent process of requests in the loadgroup. r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D110233
This commit is contained in:
Peter Van der Beken 2021-04-19 14:50:55 +00:00
Родитель d2466bf821
Коммит 14377359b0
5 изменённых файлов: 143 добавлений и 0 удалений

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

@ -36,6 +36,7 @@
#include "mozilla/SchedulerGroup.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/ScrollTypes.h"
#include "mozilla/SimpleEnumerator.h"
#include "mozilla/StaticPrefs_browser.h"
#include "mozilla/StaticPrefs_docshell.h"
#include "mozilla/StaticPrefs_dom.h"
@ -290,6 +291,7 @@ static mozilla::LazyLogModule gDocShellAndDOMWindowLeakLogging(
static mozilla::LazyLogModule gDocShellLeakLog("nsDocShellLeak");
extern mozilla::LazyLogModule gPageCacheLog;
mozilla::LazyLogModule gSHLog("SessionHistory");
extern mozilla::LazyLogModule gSHIPBFCacheLog;
const char kBrandBundleURL[] = "chrome://branding/locale/brand.properties";
const char kAppstringsBundleURL[] =
@ -13589,3 +13591,102 @@ void nsDocShell::MoveLoadingToActiveEntry(bool aPersist) {
hadActiveEntry, aPersist, false);
}
}
void nsDocShell::RecordSingleChannelId() {
if (mLoadGroup && mBrowsingContext->GetCurrentWindowContext()) {
Maybe<uint64_t> singleChannelId;
nsCOMPtr<nsISimpleEnumerator> requests;
mLoadGroup->GetRequests(getter_AddRefs(requests));
for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) {
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
// Ignore favicon loads, they don't need to block caching.
nsCOMPtr<nsILoadInfo> li;
if (channel && (li = channel->LoadInfo()) &&
li->InternalContentPolicyType() ==
nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON) {
continue;
}
// If we already found a channel ID or this is not an nsIIdentChannel then
// we have more than one request in the loadgroup.
nsCOMPtr<nsIIdentChannel> identChannel;
if (singleChannelId.isSome() ||
!(identChannel = do_QueryInterface(channel))) {
// We really have three states: no request, one request with an id and
// eiher one request without an id or multiple requests. Nothing() is no
// request, Some(non-zero) is one request and Some(0) is one request
// without an id or multiple requests.
singleChannelId = Some(0);
break;
}
singleChannelId = Some(identChannel->ChannelId());
}
if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))) {
nsAutoCString uri("[no uri]");
if (mCurrentURI) {
uri = mCurrentURI->GetSpecOrDefault();
}
if (singleChannelId.isNothing()) {
MOZ_LOG(gSHIPBFCacheLog, LogLevel::Verbose,
("Loadgroup for %s doesn't have any requests relevant for "
"blocking BFCache",
uri.get()));
} else if (singleChannelId.value() == 0) {
MOZ_LOG(gSHIPBFCacheLog, LogLevel::Verbose,
("Loadgroup for %s has multiple requests relevant for blocking "
"BFCache",
uri.get()));
} else {
MOZ_LOG(gSHIPBFCacheLog, LogLevel::Verbose,
("Loadgroup for %s has one request with id %" PRIu64
" relevant for blocking BFCache",
uri.get(), singleChannelId.value()));
}
}
if (mSingleChannelId != singleChannelId) {
mSingleChannelId = singleChannelId;
WindowGlobalChild* wgc =
mBrowsingContext->GetCurrentWindowContext()->GetWindowGlobalChild();
if (wgc) {
wgc->SendSetSingleChannelId(singleChannelId);
}
}
}
}
NS_IMETHODIMP
nsDocShell::OnStartRequest(nsIRequest* aRequest) {
if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))) {
nsAutoCString uri("[no uri]");
if (mCurrentURI) {
uri = mCurrentURI->GetSpecOrDefault();
}
nsAutoCString name;
aRequest->GetName(name);
MOZ_LOG(gSHIPBFCacheLog, LogLevel::Verbose,
("Adding request %s to loadgroup for %s", name.get(), uri.get()));
}
RecordSingleChannelId();
return nsDocLoader::OnStartRequest(aRequest);
}
NS_IMETHODIMP
nsDocShell::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) {
if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))) {
nsAutoCString uri("[no uri]");
if (mCurrentURI) {
uri = mCurrentURI->GetSpecOrDefault();
}
nsAutoCString name;
aRequest->GetName(name);
MOZ_LOG(
gSHIPBFCacheLog, LogLevel::Verbose,
("Removing request %s from loadgroup for %s", name.get(), uri.get()));
}
RecordSingleChannelId();
return nsDocLoader::OnStopRequest(aRequest, aStatusCode);
}

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

@ -511,6 +511,10 @@ class nsDocShell final : public nsDocLoader,
// This returns true only when using session history in parent.
bool IsLoadingFromSessionHistory();
NS_IMETHODIMP OnStartRequest(nsIRequest* aRequest) override;
NS_IMETHODIMP OnStopRequest(nsIRequest* aRequest,
nsresult aStatusCode) override;
private: // member functions
friend class nsDSURIContentListener;
friend class FramingChecker;
@ -713,6 +717,8 @@ class nsDocShell final : public nsDocLoader,
nsIContentSecurityPolicy* aCsp, bool aFireOnLocationChange,
bool aAddToGlobalHistory, bool aCloneSHChildren);
void RecordSingleChannelId();
public:
// Helper method that is called when a new document (including any
// sub-documents - ie. frames) has been completely loaded.
@ -1215,6 +1221,9 @@ class nsDocShell final : public nsDocLoader,
// Possible values are defined as constants in nsIDocShell.idl.
MetaViewportOverride mMetaViewportOverride;
// See WindowGlobalParent::mSingleChannelId.
mozilla::Maybe<uint64_t> mSingleChannelId;
// The following two fields cannot be declared as bit fields
// because of uses with AutoRestore.
bool mCreatingDocument; // (should be) debugging only

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

@ -186,6 +186,16 @@ parent:
// enum for the valid flags.
async UpdateBFCacheStatus(uint16_t aOnFlags, uint16_t aOffFlags);
/**
* Used to notify the parent when there's a change in the number of requests
* in the loadgroup. If there are no requests this will be set to Nothing().
* If there is one request this will be set to the ID of that request, if it
* implements nsIIdentChannel. If there are more than one requests this will
* be set to 0.
* Note that some requests are ignored (eg. favicon loads).
*/
async SetSingleChannelId(uint64_t? singleChannelId);
async Destroy();
};

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

@ -1369,6 +1369,12 @@ mozilla::ipc::IPCResult WindowGlobalParent::RecvUpdateBFCacheStatus(
return IPC_OK();
}
mozilla::ipc::IPCResult WindowGlobalParent::RecvSetSingleChannelId(
const Maybe<uint64_t>& aSingleChannelId) {
mSingleChannelId = aSingleChannelId;
return IPC_OK();
}
void WindowGlobalParent::ActorDestroy(ActorDestroyReason aWhy) {
if (mPageUseCountersWindow) {
mPageUseCountersWindow->FinishAccumulatingPageUseCounters();

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

@ -213,6 +213,8 @@ class WindowGlobalParent final : public WindowContext,
const Maybe<nsPoint>& aScrollPosition,
uint32_t aEpoch);
Maybe<uint64_t> GetSingleChannelId() { return mSingleChannelId; }
protected:
already_AddRefed<JSActor> InitJSActor(JS::HandleObject aMaybeActor,
const nsACString& aName,
@ -283,6 +285,10 @@ class WindowGlobalParent final : public WindowContext,
mozilla::ipc::IPCResult RecvUpdateBFCacheStatus(const uint16_t& aOnFlags,
const uint16_t& aOffFlags);
public:
mozilla::ipc::IPCResult RecvSetSingleChannelId(
const Maybe<uint64_t>& aSingleChannelId);
private:
WindowGlobalParent(CanonicalBrowsingContext* aBrowsingContext,
uint64_t aInnerWindowId, uint64_t aOuterWindowId,
@ -357,6 +363,17 @@ class WindowGlobalParent final : public WindowContext,
bool mSentPageUseCounters = false;
uint16_t mBFCacheStatus = 0;
// mSingleChannelId records whether the loadgroup contains a single request
// with an id. If there is one channel in the loadgroup and it has an id then
// mSingleChannelId is set to Some(id) (ids are non-zero). If there is one
// request in the loadgroup and it's not a channel or it doesn't have an id,
// or there are multiple requests in the loadgroup, then mSingleChannelId is
// set to Some(0). If there are no requests in the loadgroup then
// mSingleChannelId is set to Nothing().
// Note: We ignore favicon loads when considering the requests in the
// loadgroup.
Maybe<uint64_t> mSingleChannelId;
};
} // namespace dom