Index: Source/core/html/HTMLAnchorElement.cpp |
diff --git a/Source/core/html/HTMLAnchorElement.cpp b/Source/core/html/HTMLAnchorElement.cpp |
index 02772e772a27d2fa40a583b746056ab1175b0066..b128ea9b44a5df2be9cf39f17a810d5c108570b6 100644 |
--- a/Source/core/html/HTMLAnchorElement.cpp |
+++ b/Source/core/html/HTMLAnchorElement.cpp |
@@ -24,6 +24,9 @@ |
#include "config.h" |
#include "core/html/HTMLAnchorElement.h" |
+#include <public/Platform.h> |
+#include <public/WebPrescientNetworking.h> |
+#include <public/WebURL.h> |
#include <wtf/text/StringBuilder.h> |
#include "HTMLNames.h" |
#include "core/dom/Attribute.h" |
@@ -53,17 +56,30 @@ |
namespace WebCore { |
+namespace { |
+ |
+void preconnectToURL(const KURL& url, WebKit::WebPreconnectMotivation motivation) |
+{ |
+ WebKit::WebPrescientNetworking* prescientNetworking = WebKit::Platform::current()->prescientNetworking(); |
+ if (!prescientNetworking) |
+ return; |
+ |
+ prescientNetworking->preconnect(url, motivation); |
+} |
+ |
+} |
+ |
class HTMLAnchorElement::PrefetchEventHandler { |
public: |
- static PassOwnPtr<PrefetchEventHandler> create() |
+ static PassOwnPtr<PrefetchEventHandler> create(HTMLAnchorElement* anchorElement) |
{ |
- return adoptPtr(new HTMLAnchorElement::PrefetchEventHandler()); |
+ return adoptPtr(new HTMLAnchorElement::PrefetchEventHandler(anchorElement)); |
} |
void handleEvent(Event* e); |
private: |
- PrefetchEventHandler(); |
+ explicit PrefetchEventHandler(HTMLAnchorElement*); |
void reset(); |
@@ -74,10 +90,15 @@ private: |
void handleGestureTapDown(Event*); |
void handleClick(Event* event); |
+ bool shouldPrefetch(const KURL&); |
+ void prefetch(WebKit::WebPreconnectMotivation); |
+ |
+ HTMLAnchorElement* m_anchorElement; |
double m_mouseOverTimestamp; |
double m_mouseDownTimestamp; |
double m_tapDownTimestamp; |
bool m_hadTapUnconfirmed; |
+ bool m_hasIssuedPreconnect; |
}; |
using namespace HTMLNames; |
@@ -648,13 +669,16 @@ void HTMLAnchorElement::setRootEditableElementForSelectionOnMouseDown(Element* e |
HTMLAnchorElement::PrefetchEventHandler* HTMLAnchorElement::prefetchEventHandler() |
{ |
if (!m_prefetchEventHandler) |
- m_prefetchEventHandler = PrefetchEventHandler::create(); |
+ m_prefetchEventHandler = PrefetchEventHandler::create(this); |
return m_prefetchEventHandler.get(); |
} |
-HTMLAnchorElement::PrefetchEventHandler::PrefetchEventHandler() |
+HTMLAnchorElement::PrefetchEventHandler::PrefetchEventHandler(HTMLAnchorElement* anchorElement) |
+ : m_anchorElement(anchorElement) |
{ |
+ ASSERT(m_anchorElement); |
+ |
reset(); |
} |
@@ -664,10 +688,14 @@ void HTMLAnchorElement::PrefetchEventHandler::reset() |
m_mouseDownTimestamp = 0; |
m_hadTapUnconfirmed = false; |
m_tapDownTimestamp = 0; |
+ m_hasIssuedPreconnect = false; |
} |
void HTMLAnchorElement::PrefetchEventHandler::handleEvent(Event* event) |
{ |
+ if (!shouldPrefetch(m_anchorElement->href())) |
+ return; |
+ |
if (event->type() == eventNames().mouseoverEvent) |
handleMouseOver(event); |
else if (event->type() == eventNames().mouseoutEvent) |
@@ -688,6 +716,8 @@ void HTMLAnchorElement::PrefetchEventHandler::handleMouseOver(Event* event) |
m_mouseOverTimestamp = event->timeStamp(); |
HistogramSupport::histogramEnumeration("MouseEventPrefetch.MouseOvers", 0, 2); |
+ |
+ prefetch(WebKit::WebPreconnectMotivationLinkMouseOver); |
} |
} |
@@ -706,6 +736,8 @@ void HTMLAnchorElement::PrefetchEventHandler::handleLeftMouseDown(Event* event) |
m_mouseDownTimestamp = event->timeStamp(); |
HistogramSupport::histogramEnumeration("MouseEventPrefetch.MouseDowns", 0, 2); |
+ |
+ prefetch(WebKit::WebPreconnectMotivationLinkMouseDown); |
} |
void HTMLAnchorElement::PrefetchEventHandler::handleGestureTapUnconfirmed(Event* event) |
@@ -713,6 +745,8 @@ void HTMLAnchorElement::PrefetchEventHandler::handleGestureTapUnconfirmed(Event* |
m_hadTapUnconfirmed = true; |
HistogramSupport::histogramEnumeration("MouseEventPrefetch.TapUnconfirmeds", 0, 2); |
+ |
+ prefetch(WebKit::WebPreconnectMotivationLinkTapUnconfirmed); |
} |
void HTMLAnchorElement::PrefetchEventHandler::handleGestureTapDown(Event* event) |
@@ -720,6 +754,8 @@ void HTMLAnchorElement::PrefetchEventHandler::handleGestureTapDown(Event* event) |
m_tapDownTimestamp = event->timeStamp(); |
HistogramSupport::histogramEnumeration("MouseEventPrefetch.TapDowns", 0, 2); |
+ |
+ prefetch(WebKit::WebPreconnectMotivationLinkTapDown); |
} |
void HTMLAnchorElement::PrefetchEventHandler::handleClick(Event* event) |
@@ -753,4 +789,37 @@ void HTMLAnchorElement::PrefetchEventHandler::handleClick(Event* event) |
reset(); |
} |
+bool HTMLAnchorElement::PrefetchEventHandler::shouldPrefetch(const KURL& url) |
+{ |
+ Document* document = m_anchorElement->document(); |
+ if (!document) |
+ return false; |
+ |
+ if (!document->securityOrigin()->canDisplay(url)) |
+ return false; |
+ |
+ if (url.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(document->url(), url)) |
+ return false; |
+ |
+ Frame* frame = document->frame(); |
+ if (!frame) |
+ return false; |
+ |
+ // Links which create new window/tab are avoided because they may require user approval interaction. |
+ if (!m_anchorElement->target().isEmpty()) |
+ return false; |
+ |
+ return true; |
+} |
+ |
+void HTMLAnchorElement::PrefetchEventHandler::prefetch(WebKit::WebPreconnectMotivation motivation) |
+{ |
+ const KURL& url = m_anchorElement->href(); |
+ |
+ if (!shouldPrefetch(url)) |
+ return; |
+ |
+ preconnectToURL(url, motivation); |
+} |
+ |
} |