mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1618298 - Update PreloadService to provide APIs to integrate with link DOM element, r=smaug
Depends on D67480 Differential Revision: https://phabricator.services.mozilla.com/D67482
This commit is contained in:
parent
0f372316ea
commit
2d65fbb465
@ -1366,7 +1366,8 @@ Document::Document(const char* aContentType)
|
||||
mGeneration(0),
|
||||
mCachedTabSizeGeneration(0),
|
||||
mNextFormNumber(0),
|
||||
mNextControlNumber(0) {
|
||||
mNextControlNumber(0),
|
||||
mPreloadService(this) {
|
||||
MOZ_LOG(gDocumentLeakPRLog, LogLevel::Debug, ("DOCUMENT %p created", this));
|
||||
|
||||
SetIsInDocument();
|
||||
|
@ -1054,6 +1054,8 @@ void nsHtml5TreeOpExecutor::SetSpeculationBase(const nsAString& aURL) {
|
||||
DebugOnly<nsresult> rv = NS_NewURI(getter_AddRefs(mSpeculationBaseURI), aURL,
|
||||
encoding, mDocument->GetDocumentURI());
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to create a URI");
|
||||
|
||||
mDocument->Preloads().SetSpeculationBase(mSpeculationBaseURI);
|
||||
}
|
||||
|
||||
void nsHtml5TreeOpExecutor::UpdateReferrerInfoFromMeta(
|
||||
|
@ -5,6 +5,12 @@
|
||||
|
||||
#include "PreloadService.h"
|
||||
|
||||
#include "mozilla/AsyncEventDispatcher.h"
|
||||
#include "mozilla/dom/HTMLLinkElement.h"
|
||||
#include "mozilla/dom/ScriptLoader.h"
|
||||
#include "mozilla/StaticPrefs_network.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
bool PreloadService::RegisterPreload(PreloadHashKey* aKey,
|
||||
@ -34,4 +40,120 @@ already_AddRefed<PreloaderBase> PreloadService::LookupPreload(
|
||||
return mPreloads.Get(aKey);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIURI> PreloadService::GetPreloadURI(const nsAString& aURL) {
|
||||
nsIURI* base = BaseURIForPreload();
|
||||
auto encoding = mDocument->GetDocumentCharacterSet();
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL, encoding, base);
|
||||
if (NS_FAILED(rv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return uri.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<PreloaderBase> PreloadService::PreloadLinkElement(
|
||||
dom::HTMLLinkElement* aLinkElement, nsContentPolicyType aPolicyType,
|
||||
nsIReferrerInfo* aReferrerInfo) {
|
||||
if (!StaticPrefs::network_preload_experimental()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!CheckReferrerURIScheme(aReferrerInfo)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aPolicyType == nsIContentPolicy::TYPE_INVALID) {
|
||||
NotifyNodeEvent(aLinkElement, false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri = aLinkElement->GetURI();
|
||||
|
||||
nsAutoString as, charset, crossOrigin, integrity, referrerPolicyAttr, srcset,
|
||||
sizes, type;
|
||||
aLinkElement->GetAs(as);
|
||||
aLinkElement->GetCharset(charset);
|
||||
aLinkElement->GetCrossOrigin(crossOrigin);
|
||||
aLinkElement->GetIntegrity(integrity);
|
||||
aLinkElement->GetReferrerPolicy(referrerPolicyAttr);
|
||||
PreloadHashKey preloadKey;
|
||||
|
||||
// * Branch according the "as" value and build the `preloadKey` value.
|
||||
if (true) {
|
||||
NotifyNodeEvent(aLinkElement, false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<PreloaderBase> preload = LookupPreload(&preloadKey);
|
||||
if (!preload) {
|
||||
// * Start preload accordint the "as" value and various other per-type
|
||||
// specific attributes.
|
||||
|
||||
preload = LookupPreload(&preloadKey);
|
||||
if (!preload) {
|
||||
NotifyNodeEvent(aLinkElement, false);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
preload->AddLinkPreloadNode(aLinkElement);
|
||||
|
||||
return preload.forget();
|
||||
}
|
||||
|
||||
// static
|
||||
void PreloadService::NotifyNodeEvent(nsINode* aNode, bool aSuccess) {
|
||||
if (!aNode->IsInComposedDoc()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We don't dispatch synchronously since |node| might be in a DocGroup
|
||||
// that we're not allowed to touch. (Our network request happens in the
|
||||
// DocGroup of one of the mSources nodes--not necessarily this one).
|
||||
|
||||
RefPtr<AsyncEventDispatcher> dispatcher = new AsyncEventDispatcher(
|
||||
aNode, aSuccess ? NS_LITERAL_STRING("load") : NS_LITERAL_STRING("error"),
|
||||
CanBubble::eNo);
|
||||
|
||||
dispatcher->RequireNodeInDocument();
|
||||
dispatcher->PostDOMEvent();
|
||||
}
|
||||
|
||||
dom::ReferrerPolicy PreloadService::PreloadReferrerPolicy(
|
||||
const nsAString& aReferrerPolicy) {
|
||||
dom::ReferrerPolicy referrerPolicy =
|
||||
dom::ReferrerInfo::ReferrerPolicyAttributeFromString(aReferrerPolicy);
|
||||
if (referrerPolicy == dom::ReferrerPolicy::_empty) {
|
||||
referrerPolicy = mDocument->GetPreloadReferrerInfo()->ReferrerPolicy();
|
||||
}
|
||||
|
||||
return referrerPolicy;
|
||||
}
|
||||
|
||||
bool PreloadService::CheckReferrerURIScheme(nsIReferrerInfo* aReferrerInfo) {
|
||||
if (!aReferrerInfo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> referrer = aReferrerInfo->GetOriginalReferrer();
|
||||
if (!referrer) {
|
||||
return false;
|
||||
}
|
||||
if (!referrer->SchemeIs("http") && !referrer->SchemeIs("https")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nsIURI* PreloadService::BaseURIForPreload() {
|
||||
nsIURI* documentURI = mDocument->GetDocumentURI();
|
||||
nsIURI* documentBaseURI = mDocument->GetDocBaseURI();
|
||||
return (documentURI == documentBaseURI)
|
||||
? (mSpeculationBaseURI ? mSpeculationBaseURI.get() : documentURI)
|
||||
: documentBaseURI;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -6,11 +6,21 @@
|
||||
#ifndef PreloadService_h__
|
||||
#define PreloadService_h__
|
||||
|
||||
#include "nsIContentPolicy.h"
|
||||
#include "nsIReferrerInfo.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "PreloaderBase.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
|
||||
class HTMLLinkElement;
|
||||
class Document;
|
||||
|
||||
} // namespace dom
|
||||
|
||||
/**
|
||||
* Intended to scope preloads and speculative loads under one roof. This class
|
||||
* is intended to be a member of dom::Document. Provides registration of
|
||||
@ -20,6 +30,8 @@ namespace mozilla {
|
||||
*/
|
||||
class PreloadService {
|
||||
public:
|
||||
explicit PreloadService(dom::Document* aDocument) : mDocument(aDocument) {}
|
||||
|
||||
// Called by resource loaders to register a running resource load. This is
|
||||
// called for a speculative load when it's started the first time, being it
|
||||
// either regular speculative load or a preload.
|
||||
@ -42,8 +54,28 @@ class PreloadService {
|
||||
// registered under the key.
|
||||
already_AddRefed<PreloaderBase> LookupPreload(PreloadHashKey* aKey) const;
|
||||
|
||||
void SetSpeculationBase(nsIURI* aURI) { mSpeculationBaseURI = aURI; }
|
||||
already_AddRefed<nsIURI> GetPreloadURI(const nsAString& aURL);
|
||||
|
||||
already_AddRefed<PreloaderBase> PreloadLinkElement(
|
||||
dom::HTMLLinkElement* aLinkElement, nsContentPolicyType aPolicyType,
|
||||
nsIReferrerInfo* aReferrerInfo);
|
||||
|
||||
static void NotifyNodeEvent(nsINode* aNode, bool aSuccess);
|
||||
|
||||
private:
|
||||
dom::ReferrerPolicy PreloadReferrerPolicy(const nsAString& aReferrerPolicy);
|
||||
bool CheckReferrerURIScheme(nsIReferrerInfo* aReferrerInfo);
|
||||
nsIURI* BaseURIForPreload();
|
||||
|
||||
private:
|
||||
nsRefPtrHashtable<PreloadHashKey, PreloaderBase> mPreloads;
|
||||
|
||||
// Raw pointer only, we are intended to be a direct member of dom::Document
|
||||
dom::Document* mDocument;
|
||||
|
||||
// Set by `nsHtml5TreeOpExecutor::SetSpeculationBase`.
|
||||
nsCOMPtr<nsIURI> mSpeculationBaseURI;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -229,7 +229,8 @@ void PreloaderBase::RemoveLinkPreloadNode(nsINode* aNode) {
|
||||
}
|
||||
|
||||
void PreloaderBase::NotifyNodeEvent(nsINode* aNode) {
|
||||
// * Notify load or error event on the node
|
||||
PreloadService::NotifyNodeEvent(
|
||||
aNode, mShouldFireLoadEvent || NS_SUCCEEDED(*mOnStopStatus));
|
||||
}
|
||||
|
||||
nsresult PreloaderBase::AsyncConsume(nsIStreamListener* aListener) {
|
||||
|
Loading…
Reference in New Issue
Block a user