| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * (C) 2000 Simon Hausmann <hausmann@kde.org> | 4 * (C) 2000 Simon Hausmann <hausmann@kde.org> |
| 5 * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserv
ed. | 5 * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserv
ed. |
| 6 * (C) 2006 Graham Dennis (graham.dennis@gmail.com) | 6 * (C) 2006 Graham Dennis (graham.dennis@gmail.com) |
| 7 * | 7 * |
| 8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
| 9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
| 10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 } | 162 } |
| 163 | 163 |
| 164 bool HTMLAnchorElement::isKeyboardFocusable() const | 164 bool HTMLAnchorElement::isKeyboardFocusable() const |
| 165 { | 165 { |
| 166 if (!isLink()) | 166 if (!isLink()) |
| 167 return HTMLElement::isKeyboardFocusable(); | 167 return HTMLElement::isKeyboardFocusable(); |
| 168 | 168 |
| 169 if (!isFocusable()) | 169 if (!isFocusable()) |
| 170 return false; | 170 return false; |
| 171 | 171 |
| 172 Page* page = document()->page(); | 172 Page* page = document().page(); |
| 173 if (!page) | 173 if (!page) |
| 174 return false; | 174 return false; |
| 175 | 175 |
| 176 if (!page->chrome().client().tabsToLinks()) | 176 if (!page->chrome().client().tabsToLinks()) |
| 177 return false; | 177 return false; |
| 178 | 178 |
| 179 if (isInCanvasSubtree()) | 179 if (isInCanvasSubtree()) |
| 180 return true; | 180 return true; |
| 181 | 181 |
| 182 return hasNonEmptyBoundingBox(); | 182 return hasNonEmptyBoundingBox(); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 | 224 |
| 225 if (isLinkClick(event) && treatLinkAsLiveForEventType(eventType(event)))
{ | 225 if (isLinkClick(event) && treatLinkAsLiveForEventType(eventType(event)))
{ |
| 226 handleClick(event); | 226 handleClick(event); |
| 227 prefetchEventHandler()->reset(); | 227 prefetchEventHandler()->reset(); |
| 228 return; | 228 return; |
| 229 } | 229 } |
| 230 | 230 |
| 231 if (rendererIsEditable()) { | 231 if (rendererIsEditable()) { |
| 232 // This keeps track of the editable block that the selection was in
(if it was in one) just before the link was clicked | 232 // This keeps track of the editable block that the selection was in
(if it was in one) just before the link was clicked |
| 233 // for the LiveWhenNotFocused editable link behavior | 233 // for the LiveWhenNotFocused editable link behavior |
| 234 if (event->type() == eventNames().mousedownEvent && event->isMouseEv
ent() && toMouseEvent(event)->button() != RightButton && document()->frame() &&
document()->frame()->selection()) { | 234 if (event->type() == eventNames().mousedownEvent && event->isMouseEv
ent() && toMouseEvent(event)->button() != RightButton && document().frame() && d
ocument().frame()->selection()) { |
| 235 setRootEditableElementForSelectionOnMouseDown(document()->frame(
)->selection()->rootEditableElement()); | 235 setRootEditableElementForSelectionOnMouseDown(document().frame()
->selection()->rootEditableElement()); |
| 236 m_wasShiftKeyDownOnMouseDown = toMouseEvent(event)->shiftKey(); | 236 m_wasShiftKeyDownOnMouseDown = toMouseEvent(event)->shiftKey(); |
| 237 } else if (event->type() == eventNames().mouseoverEvent) { | 237 } else if (event->type() == eventNames().mouseoverEvent) { |
| 238 // These are cleared on mouseover and not mouseout because their
values are needed for drag events, | 238 // These are cleared on mouseover and not mouseout because their
values are needed for drag events, |
| 239 // but drag events happen after mouse out events. | 239 // but drag events happen after mouse out events. |
| 240 clearRootEditableElementForSelectionOnMouseDown(); | 240 clearRootEditableElementForSelectionOnMouseDown(); |
| 241 m_wasShiftKeyDownOnMouseDown = false; | 241 m_wasShiftKeyDownOnMouseDown = false; |
| 242 } | 242 } |
| 243 } | 243 } |
| 244 } | 244 } |
| 245 | 245 |
| 246 HTMLElement::defaultEventHandler(event); | 246 HTMLElement::defaultEventHandler(event); |
| 247 } | 247 } |
| 248 | 248 |
| 249 void HTMLAnchorElement::setActive(bool down, bool pause) | 249 void HTMLAnchorElement::setActive(bool down, bool pause) |
| 250 { | 250 { |
| 251 if (rendererIsEditable()) { | 251 if (rendererIsEditable()) { |
| 252 EditableLinkBehavior editableLinkBehavior = EditableLinkDefaultBehavior; | 252 EditableLinkBehavior editableLinkBehavior = EditableLinkDefaultBehavior; |
| 253 if (Settings* settings = document()->settings()) | 253 if (Settings* settings = document().settings()) |
| 254 editableLinkBehavior = settings->editableLinkBehavior(); | 254 editableLinkBehavior = settings->editableLinkBehavior(); |
| 255 | 255 |
| 256 switch (editableLinkBehavior) { | 256 switch (editableLinkBehavior) { |
| 257 default: | 257 default: |
| 258 case EditableLinkDefaultBehavior: | 258 case EditableLinkDefaultBehavior: |
| 259 case EditableLinkAlwaysLive: | 259 case EditableLinkAlwaysLive: |
| 260 break; | 260 break; |
| 261 | 261 |
| 262 case EditableLinkNeverLive: | 262 case EditableLinkNeverLive: |
| 263 return; | 263 return; |
| 264 | 264 |
| 265 // Don't set the link to be active if the current selection is in th
e same editable block as | 265 // Don't set the link to be active if the current selection is in th
e same editable block as |
| 266 // this link | 266 // this link |
| 267 case EditableLinkLiveWhenNotFocused: | 267 case EditableLinkLiveWhenNotFocused: |
| 268 if (down && document()->frame() && document()->frame()->selectio
n()->rootEditableElement() == rootEditableElement()) | 268 if (down && document().frame() && document().frame()->selection(
)->rootEditableElement() == rootEditableElement()) |
| 269 return; | 269 return; |
| 270 break; | 270 break; |
| 271 | 271 |
| 272 case EditableLinkOnlyLiveWithShiftKey: | 272 case EditableLinkOnlyLiveWithShiftKey: |
| 273 return; | 273 return; |
| 274 } | 274 } |
| 275 | 275 |
| 276 } | 276 } |
| 277 | 277 |
| 278 ContainerNode::setActive(down, pause); | 278 ContainerNode::setActive(down, pause); |
| 279 } | 279 } |
| 280 | 280 |
| 281 void HTMLAnchorElement::parseAttribute(const QualifiedName& name, const AtomicSt
ring& value) | 281 void HTMLAnchorElement::parseAttribute(const QualifiedName& name, const AtomicSt
ring& value) |
| 282 { | 282 { |
| 283 if (name == hrefAttr) { | 283 if (name == hrefAttr) { |
| 284 bool wasLink = isLink(); | 284 bool wasLink = isLink(); |
| 285 setIsLink(!value.isNull()); | 285 setIsLink(!value.isNull()); |
| 286 if (wasLink != isLink()) { | 286 if (wasLink != isLink()) { |
| 287 didAffectSelector(AffectedSelectorLink | AffectedSelectorVisited | A
ffectedSelectorEnabled); | 287 didAffectSelector(AffectedSelectorLink | AffectedSelectorVisited | A
ffectedSelectorEnabled); |
| 288 if (wasLink && treeScope()->adjustedFocusedElement() == this) { | 288 if (wasLink && treeScope()->adjustedFocusedElement() == this) { |
| 289 // We might want to call blur(), but it's dangerous to dispatch | 289 // We might want to call blur(), but it's dangerous to dispatch |
| 290 // events here. | 290 // events here. |
| 291 document()->setNeedsFocusedElementCheck(); | 291 document().setNeedsFocusedElementCheck(); |
| 292 } | 292 } |
| 293 } | 293 } |
| 294 if (isLink()) { | 294 if (isLink()) { |
| 295 String parsedURL = stripLeadingAndTrailingHTMLSpaces(value); | 295 String parsedURL = stripLeadingAndTrailingHTMLSpaces(value); |
| 296 if (document()->isDNSPrefetchEnabled()) { | 296 if (document().isDNSPrefetchEnabled()) { |
| 297 if (protocolIs(parsedURL, "http") || protocolIs(parsedURL, "http
s") || parsedURL.startsWith("//")) | 297 if (protocolIs(parsedURL, "http") || protocolIs(parsedURL, "http
s") || parsedURL.startsWith("//")) |
| 298 prefetchDNS(document()->completeURL(parsedURL).host()); | 298 prefetchDNS(document().completeURL(parsedURL).host()); |
| 299 } | 299 } |
| 300 | 300 |
| 301 if (wasLink) | 301 if (wasLink) |
| 302 prefetchEventHandler()->didChangeHREF(); | 302 prefetchEventHandler()->didChangeHREF(); |
| 303 } | 303 } |
| 304 invalidateCachedVisitedLinkHash(); | 304 invalidateCachedVisitedLinkHash(); |
| 305 } else if (name == nameAttr || name == titleAttr) { | 305 } else if (name == nameAttr || name == titleAttr) { |
| 306 // Do nothing. | 306 // Do nothing. |
| 307 } else if (name == relAttr) | 307 } else if (name == relAttr) |
| 308 setRel(value); | 308 setRel(value); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 334 const AtomicString& value = getAttribute(draggableAttr); | 334 const AtomicString& value = getAttribute(draggableAttr); |
| 335 if (equalIgnoringCase(value, "true")) | 335 if (equalIgnoringCase(value, "true")) |
| 336 return true; | 336 return true; |
| 337 if (equalIgnoringCase(value, "false")) | 337 if (equalIgnoringCase(value, "false")) |
| 338 return false; | 338 return false; |
| 339 return hasAttribute(hrefAttr); | 339 return hasAttribute(hrefAttr); |
| 340 } | 340 } |
| 341 | 341 |
| 342 KURL HTMLAnchorElement::href() const | 342 KURL HTMLAnchorElement::href() const |
| 343 { | 343 { |
| 344 return document()->completeURL(stripLeadingAndTrailingHTMLSpaces(getAttribut
e(hrefAttr))); | 344 return document().completeURL(stripLeadingAndTrailingHTMLSpaces(getAttribute
(hrefAttr))); |
| 345 } | 345 } |
| 346 | 346 |
| 347 void HTMLAnchorElement::setHref(const AtomicString& value) | 347 void HTMLAnchorElement::setHref(const AtomicString& value) |
| 348 { | 348 { |
| 349 setAttribute(hrefAttr, value); | 349 setAttribute(hrefAttr, value); |
| 350 } | 350 } |
| 351 | 351 |
| 352 bool HTMLAnchorElement::hasRel(uint32_t relation) const | 352 bool HTMLAnchorElement::hasRel(uint32_t relation) const |
| 353 { | 353 { |
| 354 return m_linkRelations & relation; | 354 return m_linkRelations & relation; |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 553 return href().string(); | 553 return href().string(); |
| 554 } | 554 } |
| 555 | 555 |
| 556 bool HTMLAnchorElement::isLiveLink() const | 556 bool HTMLAnchorElement::isLiveLink() const |
| 557 { | 557 { |
| 558 return isLink() && treatLinkAsLiveForEventType(m_wasShiftKeyDownOnMouseDown
? MouseEventWithShiftKey : MouseEventWithoutShiftKey); | 558 return isLink() && treatLinkAsLiveForEventType(m_wasShiftKeyDownOnMouseDown
? MouseEventWithShiftKey : MouseEventWithoutShiftKey); |
| 559 } | 559 } |
| 560 | 560 |
| 561 void HTMLAnchorElement::sendPings(const KURL& destinationURL) | 561 void HTMLAnchorElement::sendPings(const KURL& destinationURL) |
| 562 { | 562 { |
| 563 if (!hasAttribute(pingAttr) || !document()->settings() || !document()->setti
ngs()->hyperlinkAuditingEnabled()) | 563 if (!hasAttribute(pingAttr) || !document().settings() || !document().setting
s()->hyperlinkAuditingEnabled()) |
| 564 return; | 564 return; |
| 565 | 565 |
| 566 SpaceSplitString pingURLs(getAttribute(pingAttr), false); | 566 SpaceSplitString pingURLs(getAttribute(pingAttr), false); |
| 567 for (unsigned i = 0; i < pingURLs.size(); i++) | 567 for (unsigned i = 0; i < pingURLs.size(); i++) |
| 568 PingLoader::sendPing(document()->frame(), document()->completeURL(pingUR
Ls[i]), destinationURL); | 568 PingLoader::sendPing(document().frame(), document().completeURL(pingURLs
[i]), destinationURL); |
| 569 } | 569 } |
| 570 | 570 |
| 571 void HTMLAnchorElement::handleClick(Event* event) | 571 void HTMLAnchorElement::handleClick(Event* event) |
| 572 { | 572 { |
| 573 event->setDefaultHandled(); | 573 event->setDefaultHandled(); |
| 574 | 574 |
| 575 Frame* frame = document()->frame(); | 575 Frame* frame = document().frame(); |
| 576 if (!frame) | 576 if (!frame) |
| 577 return; | 577 return; |
| 578 | 578 |
| 579 StringBuilder url; | 579 StringBuilder url; |
| 580 url.append(stripLeadingAndTrailingHTMLSpaces(fastGetAttribute(hrefAttr))); | 580 url.append(stripLeadingAndTrailingHTMLSpaces(fastGetAttribute(hrefAttr))); |
| 581 appendServerMapMousePosition(url, event); | 581 appendServerMapMousePosition(url, event); |
| 582 KURL completedURL = document()->completeURL(url.toString()); | 582 KURL completedURL = document().completeURL(url.toString()); |
| 583 | 583 |
| 584 ResourceRequest request(completedURL); | 584 ResourceRequest request(completedURL); |
| 585 if (prefetchEventHandler()->hasIssuedPreconnect()) | 585 if (prefetchEventHandler()->hasIssuedPreconnect()) |
| 586 frame->loader()->client()->dispatchWillRequestAfterPreconnect(request); | 586 frame->loader()->client()->dispatchWillRequestAfterPreconnect(request); |
| 587 if (hasAttribute(downloadAttr)) { | 587 if (hasAttribute(downloadAttr)) { |
| 588 if (!hasRel(RelationNoReferrer)) { | 588 if (!hasRel(RelationNoReferrer)) { |
| 589 String referrer = SecurityPolicy::generateReferrerHeader(document()-
>referrerPolicy(), completedURL, frame->loader()->outgoingReferrer()); | 589 String referrer = SecurityPolicy::generateReferrerHeader(document().
referrerPolicy(), completedURL, frame->loader()->outgoingReferrer()); |
| 590 if (!referrer.isEmpty()) | 590 if (!referrer.isEmpty()) |
| 591 request.setHTTPReferrer(referrer); | 591 request.setHTTPReferrer(referrer); |
| 592 } | 592 } |
| 593 | 593 |
| 594 frame->loader()->client()->loadURLExternally(request, NavigationPolicyDo
wnload, fastGetAttribute(downloadAttr)); | 594 frame->loader()->client()->loadURLExternally(request, NavigationPolicyDo
wnload, fastGetAttribute(downloadAttr)); |
| 595 } else { | 595 } else { |
| 596 FrameLoadRequest frameRequest(document()->securityOrigin(), request, tar
get()); | 596 FrameLoadRequest frameRequest(document().securityOrigin(), request, targ
et()); |
| 597 frameRequest.setTriggeringEvent(event); | 597 frameRequest.setTriggeringEvent(event); |
| 598 if (hasRel(RelationNoReferrer)) | 598 if (hasRel(RelationNoReferrer)) |
| 599 frameRequest.setShouldSendReferrer(NeverSendReferrer); | 599 frameRequest.setShouldSendReferrer(NeverSendReferrer); |
| 600 frame->loader()->load(frameRequest); | 600 frame->loader()->load(frameRequest); |
| 601 } | 601 } |
| 602 | 602 |
| 603 sendPings(completedURL); | 603 sendPings(completedURL); |
| 604 } | 604 } |
| 605 | 605 |
| 606 HTMLAnchorElement::EventType HTMLAnchorElement::eventType(Event* event) | 606 HTMLAnchorElement::EventType HTMLAnchorElement::eventType(Event* event) |
| 607 { | 607 { |
| 608 if (!event->isMouseEvent()) | 608 if (!event->isMouseEvent()) |
| 609 return NonMouseEvent; | 609 return NonMouseEvent; |
| 610 return toMouseEvent(event)->shiftKey() ? MouseEventWithShiftKey : MouseEvent
WithoutShiftKey; | 610 return toMouseEvent(event)->shiftKey() ? MouseEventWithShiftKey : MouseEvent
WithoutShiftKey; |
| 611 } | 611 } |
| 612 | 612 |
| 613 bool HTMLAnchorElement::treatLinkAsLiveForEventType(EventType eventType) const | 613 bool HTMLAnchorElement::treatLinkAsLiveForEventType(EventType eventType) const |
| 614 { | 614 { |
| 615 if (!rendererIsEditable()) | 615 if (!rendererIsEditable()) |
| 616 return true; | 616 return true; |
| 617 | 617 |
| 618 Settings* settings = document()->settings(); | 618 Settings* settings = document().settings(); |
| 619 if (!settings) | 619 if (!settings) |
| 620 return true; | 620 return true; |
| 621 | 621 |
| 622 switch (settings->editableLinkBehavior()) { | 622 switch (settings->editableLinkBehavior()) { |
| 623 case EditableLinkDefaultBehavior: | 623 case EditableLinkDefaultBehavior: |
| 624 case EditableLinkAlwaysLive: | 624 case EditableLinkAlwaysLive: |
| 625 return true; | 625 return true; |
| 626 | 626 |
| 627 case EditableLinkNeverLive: | 627 case EditableLinkNeverLive: |
| 628 return false; | 628 return false; |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 815 { | 815 { |
| 816 if (m_hadHREFChanged) | 816 if (m_hadHREFChanged) |
| 817 return false; | 817 return false; |
| 818 | 818 |
| 819 if (m_anchorElement->hasEventListeners(eventNames().clickEvent)) | 819 if (m_anchorElement->hasEventListeners(eventNames().clickEvent)) |
| 820 return false; | 820 return false; |
| 821 | 821 |
| 822 if (!url.protocolIsInHTTPFamily()) | 822 if (!url.protocolIsInHTTPFamily()) |
| 823 return false; | 823 return false; |
| 824 | 824 |
| 825 Document* document = m_anchorElement->document(); | 825 Document& document = m_anchorElement->document(); |
| 826 if (!document) | 826 |
| 827 if (!document.securityOrigin()->canDisplay(url)) |
| 827 return false; | 828 return false; |
| 828 | 829 |
| 829 if (!document->securityOrigin()->canDisplay(url)) | 830 if (url.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(document.
url(), url)) |
| 830 return false; | 831 return false; |
| 831 | 832 |
| 832 if (url.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(document-
>url(), url)) | 833 Frame* frame = document.frame(); |
| 833 return false; | |
| 834 | |
| 835 Frame* frame = document->frame(); | |
| 836 if (!frame) | 834 if (!frame) |
| 837 return false; | 835 return false; |
| 838 | 836 |
| 839 // Links which create new window/tab are avoided because they may require us
er approval interaction. | 837 // Links which create new window/tab are avoided because they may require us
er approval interaction. |
| 840 if (!m_anchorElement->target().isEmpty()) | 838 if (!m_anchorElement->target().isEmpty()) |
| 841 return false; | 839 return false; |
| 842 | 840 |
| 843 return true; | 841 return true; |
| 844 } | 842 } |
| 845 | 843 |
| 846 void HTMLAnchorElement::PrefetchEventHandler::prefetch(WebKit::WebPreconnectMoti
vation motivation) | 844 void HTMLAnchorElement::PrefetchEventHandler::prefetch(WebKit::WebPreconnectMoti
vation motivation) |
| 847 { | 845 { |
| 848 const KURL& url = m_anchorElement->href(); | 846 const KURL& url = m_anchorElement->href(); |
| 849 | 847 |
| 850 if (!shouldPrefetch(url)) | 848 if (!shouldPrefetch(url)) |
| 851 return; | 849 return; |
| 852 | 850 |
| 853 // The precision of current MouseOver trigger is too low to actually trigger
preconnects. | 851 // The precision of current MouseOver trigger is too low to actually trigger
preconnects. |
| 854 if (motivation == WebKit::WebPreconnectMotivationLinkMouseOver) | 852 if (motivation == WebKit::WebPreconnectMotivationLinkMouseOver) |
| 855 return; | 853 return; |
| 856 | 854 |
| 857 preconnectToURL(url, motivation); | 855 preconnectToURL(url, motivation); |
| 858 m_hasIssuedPreconnect = true; | 856 m_hasIssuedPreconnect = true; |
| 859 } | 857 } |
| 860 | 858 |
| 861 } | 859 } |
| OLD | NEW |