Bug 1603542 - Log a warning in the web console when a preloaded resource is not used, r=Harald

Differential Revision: https://phabricator.services.mozilla.com/D76527
This commit is contained in:
Honza Bambas 2020-06-23 17:18:20 +00:00
parent 5c0d68416b
commit 3f23870623
3 changed files with 71 additions and 3 deletions

View File

@ -389,3 +389,5 @@ WebShareAPI_Aborted=The share operation was aborted.
# LOCALIZATION NOTE (UnknownProtocolNavigationPrevented): %1$S is the destination URL.
UnknownProtocolNavigationPrevented=Prevented navigation to “%1$S” due to an unknown protocol.
PostMessageSharedMemoryObjectToCrossOriginWarning=Cannot post message containing a shared memory object to a cross-origin window.
# LOCALIZATION NOTE: %S is the URL of the resource in question
UnusedLinkPreloadPending=The resource at “%S” preloaded with link preload was not used within a few seconds. Make sure all attributes of the preload tag are set correctly.

View File

@ -5,6 +5,7 @@
#include "PreloaderBase.h"
#include "mozilla/dom/Document.h"
#include "nsContentUtils.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsIChannel.h"
#include "nsILoadGroup.h"
@ -111,7 +112,9 @@ void PreloaderBase::NotifyOpen(const PreloadHashKey& aKey, nsIChannel* aChannel,
NotifyOpen(aKey, aDocument, aIsPreload);
mChannel = aChannel;
// * Start the usage timer if aIsPreload.
auto callback = MakeRefPtr<UsageTimer>(this, aDocument);
NS_NewTimerWithCallback(getter_AddRefs(mUsageTimer), callback, 10000,
nsITimer::TYPE_ONE_SHOT);
nsCOMPtr<nsIInterfaceRequestor> callbacks;
mChannel->GetNotificationCallbacks(getter_AddRefs(callbacks));
@ -146,8 +149,7 @@ void PreloaderBase::NotifyUsage(LoadBackground aLoadBackground) {
}
mIsUsed = true;
// * Cancel the usage timer.
CancelUsageTimer();
}
void PreloaderBase::RemoveSelf(dom::Document* aDocument) {
@ -161,6 +163,8 @@ void PreloaderBase::NotifyRestart(dom::Document* aDocument,
RemoveSelf(aDocument);
mKey = PreloadHashKey();
CancelUsageTimer();
if (aNewPreloader) {
aNewPreloader->mNodes = std::move(mNodes);
}
@ -254,6 +258,13 @@ void PreloaderBase::NotifyNodeEvent(nsINode* aNode) {
aNode, mShouldFireLoadEvent || NS_SUCCEEDED(*mOnStopStatus));
}
void PreloaderBase::CancelUsageTimer() {
if (mUsageTimer) {
mUsageTimer->Cancel();
mUsageTimer = nullptr;
}
}
nsresult PreloaderBase::AsyncConsume(nsIStreamListener* aListener) {
// We want to return an error so that consumers can't ever use a preload to
// consume data unless it's properly implemented.
@ -275,4 +286,38 @@ nsCString PreloaderBase::RedirectRecord::Fragment() const {
return fragment;
}
// PreloaderBase::UsageTimer
NS_IMPL_ISUPPORTS(PreloaderBase::UsageTimer, nsITimerCallback)
NS_IMETHODIMP PreloaderBase::UsageTimer::Notify(nsITimer* aTimer) {
if (!mPreload || !mDocument) {
return NS_OK;
}
MOZ_ASSERT(aTimer == mPreload->mUsageTimer);
mPreload->mUsageTimer = nullptr;
if (mPreload->IsUsed()) {
// Left in the hashtable, but marked as used. This is a valid case, and we
// don't want to emit a warning for this preload then.
return NS_OK;
}
// PreloadHashKey overrides GetKey, we need to use the nsURIHashKey one to get
// the URI.
nsIURI* uri = static_cast<nsURIHashKey*>(&mPreload->mKey)->GetKey();
if (!uri) {
return NS_OK;
}
nsString spec = NS_ConvertUTF8toUTF16(uri->GetSpecOrDefault());
nsContentUtils::ReportToConsole(
nsIScriptError::warningFlag, NS_LITERAL_CSTRING("DOM"), mDocument,
nsContentUtils::eDOM_PROPERTIES, "UnusedLinkPreloadPending",
nsTArray<nsString>({spec}));
return NS_OK;
}
} // namespace mozilla

View File

@ -11,6 +11,7 @@
#include "nsIChannelEventSink.h"
#include "nsIInterfaceRequestor.h"
#include "nsIRedirectResultListener.h"
#include "nsITimer.h"
#include "nsIURI.h"
#include "nsTArray.h"
#include "nsProxyRelease.h"
@ -141,6 +142,7 @@ class PreloaderBase : public SupportsWeakPtr<PreloaderBase>,
private:
void NotifyNodeEvent(nsINode* aNode);
void CancelUsageTimer();
// A helper class that will update the PreloaderBase.mChannel member when a
// redirect happens, so that we can reprioritize or cancel when needed.
@ -168,6 +170,21 @@ class PreloaderBase : public SupportsWeakPtr<PreloaderBase>,
nsCOMPtr<nsIChannel> mRedirectChannel;
};
// A timer callback to trigger the unuse warning for this preload
class UsageTimer final : public nsITimerCallback {
NS_DECL_ISUPPORTS
NS_DECL_NSITIMERCALLBACK
UsageTimer(PreloaderBase* aPreload, dom::Document* aDocument)
: mDocument(aDocument), mPreload(aPreload) {}
private:
~UsageTimer() = default;
WeakPtr<dom::Document> mDocument;
WeakPtr<PreloaderBase> mPreload;
};
private:
// Reference to HTMLLinkElement DOM nodes to deliver onload and onerror
// notifications to.
@ -176,6 +193,10 @@ class PreloaderBase : public SupportsWeakPtr<PreloaderBase>,
// History of redirects.
nsTArray<RedirectRecord> mRedirectRecords;
// Usage timer, emits warning when the preload is not used in time. Started
// in NotifyOpen and stopped in NotifyUsage.
nsCOMPtr<nsITimer> mUsageTimer;
// The key this preload has been registered under. We want to remember it to
// be able to deregister itself from the document's preloads.
PreloadHashKey mKey;