зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1134648, handle dynamic changes to rel=dns-prefetch, r=bz
--HG-- extra : rebase_source : 817f331da1cfadb0833a14a3a18c5d4769752b79
This commit is contained in:
Родитель
ff55707b83
Коммит
cc8c87cbc0
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "nsEscape.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsHTMLDNSPrefetch.h"
|
||||
#include "nsString.h"
|
||||
#include "mozAutoDocUpdate.h"
|
||||
|
||||
|
@ -46,6 +47,31 @@ Link::ElementHasHref() const
|
|||
mElement->HasAttr(kNameSpaceID_XLink, nsGkAtoms::href)));
|
||||
}
|
||||
|
||||
void
|
||||
Link::TryDNSPrefetch()
|
||||
{
|
||||
MOZ_ASSERT(mElement->IsInComposedDoc());
|
||||
if (ElementHasHref() && nsHTMLDNSPrefetch::IsAllowed(mElement->OwnerDoc())) {
|
||||
nsHTMLDNSPrefetch::PrefetchLow(this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Link::CancelDNSPrefetch(nsWrapperCache::FlagsType aDeferredFlag,
|
||||
nsWrapperCache::FlagsType aRequestedFlag)
|
||||
{
|
||||
// If prefetch was deferred, clear flag and move on
|
||||
if (mElement->HasFlag(aDeferredFlag)) {
|
||||
mElement->UnsetFlags(aDeferredFlag);
|
||||
// Else if prefetch was requested, clear flag and send cancellation
|
||||
} else if (mElement->HasFlag(aRequestedFlag)) {
|
||||
mElement->UnsetFlags(aRequestedFlag);
|
||||
// Possible that hostname could have changed since binding, but since this
|
||||
// covers common cases, most DNS prefetch requests will be canceled
|
||||
nsHTMLDNSPrefetch::CancelPrefetchLow(this, NS_ERROR_ABORT);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Link::SetLinkState(nsLinkState aState)
|
||||
{
|
||||
|
|
|
@ -111,6 +111,11 @@ public:
|
|||
|
||||
bool ElementHasHref() const;
|
||||
|
||||
void TryDNSPrefetch();
|
||||
|
||||
void CancelDNSPrefetch(nsWrapperCache::FlagsType aDeferredFlag,
|
||||
nsWrapperCache::FlagsType aRequestedFlag);
|
||||
|
||||
protected:
|
||||
virtual ~Link();
|
||||
|
||||
|
|
|
@ -158,9 +158,7 @@ HTMLAnchorElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
|||
nsIDocument* doc = GetComposedDoc();
|
||||
if (doc) {
|
||||
doc->RegisterPendingLinkUpdate(this);
|
||||
if (nsHTMLDNSPrefetch::IsAllowed(OwnerDoc())) {
|
||||
nsHTMLDNSPrefetch::PrefetchLow(this);
|
||||
}
|
||||
TryDNSPrefetch();
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -172,18 +170,9 @@ HTMLAnchorElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
|||
// Cancel any DNS prefetches
|
||||
// Note: Must come before ResetLinkState. If called after, it will recreate
|
||||
// mCachedURI based on data that is invalid - due to a call to GetHostname.
|
||||
CancelDNSPrefetch(HTML_ANCHOR_DNS_PREFETCH_DEFERRED,
|
||||
HTML_ANCHOR_DNS_PREFETCH_REQUESTED);
|
||||
|
||||
// If prefetch was deferred, clear flag and move on
|
||||
if (HasFlag(HTML_ANCHOR_DNS_PREFETCH_DEFERRED))
|
||||
UnsetFlags(HTML_ANCHOR_DNS_PREFETCH_DEFERRED);
|
||||
// Else if prefetch was requested, clear flag and send cancellation
|
||||
else if (HasFlag(HTML_ANCHOR_DNS_PREFETCH_REQUESTED)) {
|
||||
UnsetFlags(HTML_ANCHOR_DNS_PREFETCH_REQUESTED);
|
||||
// Possible that hostname could have changed since binding, but since this
|
||||
// covers common cases, most DNS prefetch requests will be canceled
|
||||
nsHTMLDNSPrefetch::CancelPrefetchLow(this, NS_ERROR_ABORT);
|
||||
}
|
||||
|
||||
// If this link is ever reinserted into a document, it might
|
||||
// be under a different xml:base, so forget the cached state now.
|
||||
Link::ResetLinkState(false, Link::ElementHasHref());
|
||||
|
@ -406,6 +395,10 @@ HTMLAnchorElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
|||
reset = true;
|
||||
}
|
||||
}
|
||||
if (reset) {
|
||||
CancelDNSPrefetch(HTML_ANCHOR_DNS_PREFETCH_DEFERRED,
|
||||
HTML_ANCHOR_DNS_PREFETCH_REQUESTED);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix,
|
||||
|
@ -418,6 +411,9 @@ HTMLAnchorElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
|||
// to get updated information about the visitedness from Link.
|
||||
if (reset) {
|
||||
Link::ResetLinkState(!!aNotify, true);
|
||||
if (IsInComposedDoc()) {
|
||||
TryDNSPrefetch();
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -427,6 +423,14 @@ nsresult
|
|||
HTMLAnchorElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
|
||||
bool aNotify)
|
||||
{
|
||||
bool href =
|
||||
(aAttribute == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID);
|
||||
|
||||
if (href) {
|
||||
CancelDNSPrefetch(HTML_ANCHOR_DNS_PREFETCH_DEFERRED,
|
||||
HTML_ANCHOR_DNS_PREFETCH_REQUESTED);
|
||||
}
|
||||
|
||||
nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttribute,
|
||||
aNotify);
|
||||
|
||||
|
@ -435,7 +439,7 @@ HTMLAnchorElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
|
|||
// we will need the updated attribute value because notifying the document
|
||||
// that content states have changed will call IntrinsicState, which will try
|
||||
// to get updated information about the visitedness from Link.
|
||||
if (aAttribute == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID) {
|
||||
if (href) {
|
||||
Link::ResetLinkState(!!aNotify, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,22 @@
|
|||
#include "nsStyleConsts.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
|
||||
#define LINK_ELEMENT_FLAG_BIT(n_) \
|
||||
NODE_FLAG_BIT(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + (n_))
|
||||
|
||||
// Link element specific bits
|
||||
enum {
|
||||
// Indicates that a DNS Prefetch has been requested from this Link element.
|
||||
HTML_LINK_DNS_PREFETCH_REQUESTED = LINK_ELEMENT_FLAG_BIT(0),
|
||||
|
||||
// Indicates that a DNS Prefetch was added to the deferral queue
|
||||
HTML_LINK_DNS_PREFETCH_DEFERRED = LINK_ELEMENT_FLAG_BIT(1)
|
||||
};
|
||||
|
||||
#undef LINK_ELEMENT_FLAG_BIT
|
||||
|
||||
ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2);
|
||||
|
||||
NS_IMPL_NS_NEW_HTML_ELEMENT(Link)
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -126,6 +142,26 @@ HTMLLinkElement::SetItemValueText(const nsAString& aValue)
|
|||
SetHref(aValue);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLLinkElement::OnDNSPrefetchRequested()
|
||||
{
|
||||
UnsetFlags(HTML_LINK_DNS_PREFETCH_DEFERRED);
|
||||
SetFlags(HTML_LINK_DNS_PREFETCH_REQUESTED);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLLinkElement::OnDNSPrefetchDeferred()
|
||||
{
|
||||
UnsetFlags(HTML_LINK_DNS_PREFETCH_REQUESTED);
|
||||
SetFlags(HTML_LINK_DNS_PREFETCH_DEFERRED);
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLLinkElement::HasDeferredDNSPrefetchRequest()
|
||||
{
|
||||
return HasFlag(HTML_LINK_DNS_PREFETCH_DEFERRED);
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLLinkElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsIContent* aBindingParent,
|
||||
|
@ -145,6 +181,9 @@ HTMLLinkElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
|||
|
||||
if (IsInComposedDoc()) {
|
||||
UpdatePreconnect();
|
||||
if (HasDNSPrefetchRel()) {
|
||||
TryDNSPrefetch();
|
||||
}
|
||||
}
|
||||
|
||||
void (HTMLLinkElement::*update)() = &HTMLLinkElement::UpdateStyleSheetInternal;
|
||||
|
@ -173,6 +212,12 @@ HTMLLinkElement::LinkRemoved()
|
|||
void
|
||||
HTMLLinkElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||
{
|
||||
// Cancel any DNS prefetches
|
||||
// Note: Must come before ResetLinkState. If called after, it will recreate
|
||||
// mCachedURI based on data that is invalid - due to a call to GetHostname.
|
||||
CancelDNSPrefetch(HTML_LINK_DNS_PREFETCH_DEFERRED,
|
||||
HTML_LINK_DNS_PREFETCH_REQUESTED);
|
||||
|
||||
// If this link is ever reinserted into a document, it might
|
||||
// be under a different xml:base, so forget the cached state now.
|
||||
Link::ResetLinkState(false, Link::ElementHasHref());
|
||||
|
@ -322,6 +367,32 @@ HTMLLinkElement::UpdatePreconnect()
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLLinkElement::HasDNSPrefetchRel()
|
||||
{
|
||||
nsAutoString rel;
|
||||
if (GetAttr(kNameSpaceID_None, nsGkAtoms::rel, rel)) {
|
||||
return !!(ParseLinkTypes(rel, NodePrincipal()) &
|
||||
nsStyleLinkElement::eDNS_PREFETCH);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLLinkElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
nsAttrValueOrString* aValue, bool aNotify)
|
||||
{
|
||||
if (aNameSpaceID == kNameSpaceID_None &&
|
||||
(aName == nsGkAtoms::href || aName == nsGkAtoms::rel)) {
|
||||
CancelDNSPrefetch(HTML_LINK_DNS_PREFETCH_DEFERRED,
|
||||
HTML_LINK_DNS_PREFETCH_REQUESTED);
|
||||
}
|
||||
|
||||
return nsGenericHTMLElement::BeforeSetAttr(aNameSpaceID, aName,
|
||||
aValue, aNotify);
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
const nsAttrValue* aValue, bool aNotify)
|
||||
|
@ -368,6 +439,11 @@ HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
|||
}
|
||||
}
|
||||
|
||||
if ((aName == nsGkAtoms::rel || aName == nsGkAtoms::href) &&
|
||||
HasDNSPrefetchRel() && IsInComposedDoc()) {
|
||||
TryDNSPrefetch();
|
||||
}
|
||||
|
||||
UpdateStyleSheetInternal(nullptr, nullptr,
|
||||
dropSheet ||
|
||||
(aName == nsGkAtoms::title ||
|
||||
|
|
|
@ -61,6 +61,9 @@ public:
|
|||
bool aCompileEventHandlers) override;
|
||||
virtual void UnbindFromTree(bool aDeep = true,
|
||||
bool aNullParent = true) override;
|
||||
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
nsAttrValueOrString* aValue,
|
||||
bool aNotify) override;
|
||||
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
const nsAttrValue* aValue,
|
||||
bool aNotify) override;
|
||||
|
@ -77,6 +80,10 @@ public:
|
|||
|
||||
void CreateAndDispatchEvent(nsIDocument* aDoc, const nsAString& aEventName);
|
||||
|
||||
virtual void OnDNSPrefetchDeferred() override;
|
||||
virtual void OnDNSPrefetchRequested() override;
|
||||
virtual bool HasDeferredDNSPrefetchRequest() override;
|
||||
|
||||
// WebIDL
|
||||
bool Disabled();
|
||||
void SetDisabled(bool aDisabled);
|
||||
|
@ -166,6 +173,9 @@ protected:
|
|||
// nsGenericHTMLElement
|
||||
virtual void GetItemValueText(DOMString& text) override;
|
||||
virtual void SetItemValueText(const nsAString& text) override;
|
||||
|
||||
bool HasDNSPrefetchRel();
|
||||
|
||||
RefPtr<nsDOMTokenList > mRelList;
|
||||
private:
|
||||
RefPtr<ImportLoader> mImportLoader;
|
||||
|
|
|
@ -611,13 +611,6 @@ nsXMLContentSink::CloseElement(nsIContent* aContent)
|
|||
PrefetchHref(hrefVal, aContent, hasPrefetch);
|
||||
}
|
||||
}
|
||||
if (linkTypes & nsStyleLinkElement::eDNS_PREFETCH) {
|
||||
nsAutoString hrefVal;
|
||||
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
|
||||
if (!hrefVal.IsEmpty()) {
|
||||
PrefetchDNS(hrefVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,13 +96,6 @@ nsHtml5DocumentBuilder::UpdateStyleSheet(nsIContent* aElement)
|
|||
PrefetchHref(hrefVal, aElement, hasPrefetch);
|
||||
}
|
||||
}
|
||||
if (linkTypes & nsStyleLinkElement::eDNS_PREFETCH) {
|
||||
nsAutoString hrefVal;
|
||||
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
|
||||
if (!hrefVal.IsEmpty()) {
|
||||
PrefetchDNS(hrefVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче