Support for multiple <link rel="icon"> favicon elements.
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 21 Sep 2011 01:49:03 +0000 (01:49 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 21 Sep 2011 01:49:03 +0000 (01:49 +0000)
https://bugs.webkit.org/show_bug.cgi?id=65564

Patch by Rachel Blum <groby@chromium.org> on 2011-09-20
Reviewed by Darin Fisher.

No tests - purely an API change. (And API is not exposed to LayoutTests)

* dom/Document.cpp:
(WebCore::Document::iconURLs):
(WebCore::Document::addIconURL):
* dom/Document.h:
* dom/IconURL.cpp:
(WebCore::toIconIndex):
* dom/IconURL.h:
(WebCore::IconURL::IconURL):
* html/HTMLLinkElement.cpp:
(WebCore::HTMLLinkElement::process):
* loader/LinkLoader.cpp:
(WebCore::LinkLoader::loadLink):
* loader/LinkLoader.h:
* loader/icon/IconController.cpp:
(WebCore::IconController::urlsForTypes):
(WebCore::IconController::appendToIconURLs):
(WebCore::IconController::defaultURL):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@95593 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
Source/WebCore/ChangeLog
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/dom/IconURL.cpp
Source/WebCore/dom/IconURL.h
Source/WebCore/html/HTMLLinkElement.cpp
Source/WebCore/loader/DocumentLoader.cpp
Source/WebCore/loader/DocumentLoader.h
Source/WebCore/loader/FrameLoader.cpp
Source/WebCore/loader/FrameLoader.h
Source/WebCore/loader/LinkLoader.cpp
Source/WebCore/loader/LinkLoader.h
Source/WebCore/loader/icon/IconController.cpp
Source/WebCore/loader/icon/IconController.h

index bbfc666..d170b06 100644 (file)
@@ -1,3 +1,30 @@
+2011-09-20  Rachel Blum  <groby@chromium.org>
+
+        Support for multiple <link rel="icon"> favicon elements.
+        https://bugs.webkit.org/show_bug.cgi?id=65564
+
+        Reviewed by Darin Fisher.
+
+        No tests - purely an API change. (And API is not exposed to LayoutTests)
+
+        * dom/Document.cpp:
+        (WebCore::Document::iconURLs):
+        (WebCore::Document::addIconURL):
+        * dom/Document.h:
+        * dom/IconURL.cpp:
+        (WebCore::toIconIndex):
+        * dom/IconURL.h:
+        (WebCore::IconURL::IconURL):
+        * html/HTMLLinkElement.cpp:
+        (WebCore::HTMLLinkElement::process):
+        * loader/LinkLoader.cpp:
+        (WebCore::LinkLoader::loadLink):
+        * loader/LinkLoader.h:
+        * loader/icon/IconController.cpp:
+        (WebCore::IconController::urlsForTypes):
+        (WebCore::IconController::appendToIconURLs):
+        (WebCore::IconController::defaultURL):
+
 2011-09-20  Ojan Vafai  <ojan@chromium.org>
 
         [css3-flexbox] cleanup padding width calculations
index b326a70..d6a252c 100644 (file)
@@ -5,7 +5,7 @@
  *           (C) 2006 Alexey Proskuryakov (ap@webkit.org)
  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved.
  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
- * Copyright (C) 2008, 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 2011 Google Inc. All rights reserved.
  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
  *
  * This library is free software; you can redistribute it and/or
@@ -4430,26 +4430,25 @@ unsigned FormElementKeyHash::hash(const FormElementKey& key)
     return StringHasher::hashMemory<sizeof(FormElementKey)>(&key);
 }
 
-IconURL Document::iconURL(IconType iconType) const
+const Vector<IconURL>& Document::iconURLs() const
 {
-    return m_iconURLs[toIconIndex(iconType)];
+    return m_iconURLs;
 }
 
-void Document::setIconURL(const String& url, const String& mimeType, IconType iconType)
+void Document::addIconURL(const String& url, const String& mimeType, const String& sizes, IconType iconType)
 {
+    if (url.isEmpty())
+        return;
+
     // FIXME - <rdar://problem/4727645> - At some point in the future, we might actually honor the "mimeType"
-    IconURL newURL(KURL(ParsedURLString, url), iconType);
-    if (iconURL(iconType).m_iconURL.isEmpty())
-        setIconURL(newURL);
-    else if (!mimeType.isEmpty())
-        setIconURL(newURL);
-    if (Frame* f = frame())
-        f->loader()->icon()->setURL(newURL);
-}
+    IconURL newURL(KURL(ParsedURLString, url), sizes, mimeType, iconType);
+    m_iconURLs.append(newURL);
 
-void Document::setIconURL(const IconURL& iconURL)
-{
-    m_iconURLs[toIconIndex(iconURL.m_iconType)] = iconURL;
+    if (Frame* f = frame()) {
+        IconURL iconURL = f->loader()->icon()->iconURL(iconType);
+        if (iconURL == newURL)
+            f->loader()->didChangeIcons(iconType);
+    }
 }
 
 void Document::registerFormElementWithFormAttribute(FormAssociatedElement* element)
index 0ea5305..85fa3a1 100644 (file)
@@ -6,6 +6,7 @@
  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2011 Google Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -917,9 +918,8 @@ public:
     
     void setHasNodesWithPlaceholderStyle() { m_hasNodesWithPlaceholderStyle = true; }
 
-    IconURL iconURL(IconType) const;
-    void setIconURL(const String&, const String&, IconType);
-    void setIconURL(const IconURL&);
+    const Vector<IconURL>& iconURLs() const;
+    void addIconURL(const String& url, const String& mimeType, const String& size, IconType);
 
     void setUseSecureKeyboardEntryWhenActive(bool);
     bool useSecureKeyboardEntryWhenActive() const;
@@ -1349,7 +1349,7 @@ private:
 
     bool m_createRenderers;
     bool m_inPageCache;
-    IconURL m_iconURLs[ICON_COUNT];
+    Vector<IconURL> m_iconURLs;
 
     HashSet<Element*> m_documentActivationCallbackElements;
     HashSet<Element*> m_mediaVolumeCallbackElements;
index 8aefc2a..d121ea3 100644 (file)
@@ -54,5 +54,21 @@ size_t toIconIndex(IconType type)
     return index;
 }
 
+IconURL IconURL::defaultIconURL(const KURL& url, IconType type)
+{
+    IconURL result(url, emptyString(), emptyString(), type);
+    result.m_isDefaultIcon = true;
+    return result;
+}
+
+bool operator==(const IconURL& lhs, const IconURL& rhs)
+{
+    return lhs.m_iconType == rhs.m_iconType
+           && lhs.m_isDefaultIcon == rhs.m_isDefaultIcon
+           && lhs.m_iconURL == rhs.m_iconURL
+           && lhs.m_sizes == rhs.m_sizes
+           && lhs.m_mimeType == rhs.m_mimeType;
+}
+
 }
 
index 6486ca4..1104795 100644 (file)
@@ -45,25 +45,36 @@ enum IconType {
     InvalidIcon = 0,
     Favicon = 1,
     TouchIcon = 1 << 1,
-    TouchPrecomposedIcon = 1 << 2
+    TouchPrecomposedIcon = 1 << 2,
 };
 
 struct IconURL {
     IconType m_iconType;
+    String m_sizes;
+    String m_mimeType;
     KURL m_iconURL;
+    bool m_isDefaultIcon;
 
     IconURL()
         : m_iconType(InvalidIcon)
+        , m_isDefaultIcon(false)
     {
     }
 
-    IconURL(const KURL& url, IconType type)
+    IconURL(const KURL& url, const String& sizes, const String& mimeType, IconType type)
         : m_iconType(type)
+        , m_sizes(sizes)
+        , m_mimeType(mimeType)
         , m_iconURL(url)
+        , m_isDefaultIcon(false)
     {
     }
+    
+    static IconURL defaultIconURL(const KURL&, IconType);
 };
 
+bool operator==(const IconURL&, const IconURL&);
+
 typedef Vector<IconURL, ICON_COUNT> IconURLs;
 
 // Returns the index of the given type, 0 is returned if the type is invalid.
index 9b954aa..52e273e 100644 (file)
@@ -179,7 +179,7 @@ void HTMLLinkElement::process()
 
     String type = m_type.lower();
 
-    if (!m_linkLoader.loadLink(m_relAttribute, type, m_url, document()))
+    if (!m_linkLoader.loadLink(m_relAttribute, type, m_sizes->toString(), m_url, document()))
         return;
 
     bool acceptIfTypeContainsTextCSS = document()->page() && document()->page()->settings() && document()->page()->settings()->treatsAnyTextCSSLinkAsStylesheet();
index 684fb66..be9112e 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Google Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -682,22 +683,6 @@ void DocumentLoader::setTitle(const StringWithDirection& title)
     }
 }
 
-IconURL DocumentLoader::iconURL(IconType iconType) const
-{
-    return m_iconURLs[toIconIndex(iconType)];
-}
-
-void DocumentLoader::setIconURL(const IconURL& url)
-{
-    if (url.m_iconURL.isEmpty())
-        return;
-
-    if (iconURL(url.m_iconType).m_iconURL != url.m_iconURL) {
-        m_iconURLs[toIconIndex(url.m_iconType)] = url;
-        frameLoader()->didChangeIcons(this, url.m_iconType);
-    }
-}
-
 KURL DocumentLoader::urlForHistory() const
 {
     // Return the URL to be used for history and B/F list.
index 5689fa2..c7e78c0 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Google Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -32,7 +33,6 @@
 #include "DocumentLoadTiming.h"
 #include "DocumentWriter.h"
 #include "IconDatabaseBase.h"
-#include "IconURL.h"
 #include "NavigationAction.h"
 #include "ResourceError.h"
 #include "ResourceRequest.h"
@@ -128,7 +128,6 @@ namespace WebCore {
         bool isLoadingInAPISense() const;
         void setPrimaryLoadComplete(bool);
         void setTitle(const StringWithDirection&);
-        void setIconURL(const IconURL&);
         const String& overrideEncoding() const { return m_overrideEncoding; }
 
 #if PLATFORM(MAC)
@@ -175,7 +174,6 @@ namespace WebCore {
 
         void stopRecordingResponses();
         const StringWithDirection& title() const { return m_pageTitle; }
-        IconURL iconURL(IconType) const;
 
         KURL urlForHistory() const;
         bool urlForHistoryReflectsFailure() const;
@@ -314,7 +312,6 @@ namespace WebCore {
         bool m_wasOnloadHandled;
 
         StringWithDirection m_pageTitle;
-        IconURL m_iconURLs[ICON_COUNT];
 
         String m_overrideEncoding;
 
index 724c676..5af67f5 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright (C) 2008 Alp Toker <alp@atoker.com>
  * Copyright (C) Research In Motion Limited 2009. All rights reserved.
  * Copyright (C) 2011 Kris Jordan <krisjordan@gmail.com>
+ * Copyright (C) 2011 Google Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -3228,10 +3229,9 @@ void FrameLoader::didChangeTitle(DocumentLoader* loader)
     }
 }
 
-void FrameLoader::didChangeIcons(DocumentLoader* loader, IconType type)
+void FrameLoader::didChangeIcons(IconType type)
 {
-    if (loader == m_documentLoader)
-        m_client->dispatchDidChangeIcons(type);
+    m_client->dispatchDidChangeIcons(type);
 }
 
 void FrameLoader::dispatchDidCommitLoad()
index ec37816..ff3d9f2 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (C) 2006, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved.
  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
  * Copyright (C) Research In Motion Limited 2009. All rights reserved.
+ * Copyright (C) 2011 Google Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -169,7 +170,7 @@ public:
     bool subframeIsLoading() const;
     void willChangeTitle(DocumentLoader*);
     void didChangeTitle(DocumentLoader*);
-    void didChangeIcons(DocumentLoader*, IconType);
+    void didChangeIcons(IconType);
 
     FrameLoadType loadType() const;
 
index b924088..51d3d8f 100644 (file)
@@ -85,13 +85,13 @@ void LinkLoader::notifyFinished(CachedResource* resource)
 }
 
 bool LinkLoader::loadLink(const LinkRelAttribute& relAttribute, const String& type,
-                          const KURL& href, Document* document)
+                          const String& sizes, const KURL& href, Document* document)
 {
     // We'll record this URL per document, even if we later only use it in top level frames
     if (relAttribute.m_iconType != InvalidIcon && href.isValid() && !href.isEmpty()) {
         if (!m_client->shouldLoadLink()) 
             return false;
-        document->setIconURL(href.string(), type, relAttribute.m_iconType);
+        document->addIconURL(href.string(), type, sizes, relAttribute.m_iconType);
     }
 
     if (relAttribute.m_isDNSPrefetch) {
index 6c448d8..1fbc18d 100644 (file)
@@ -50,7 +50,7 @@ public:
     // from CachedResourceClient
     virtual void notifyFinished(CachedResource*);
     
-    bool loadLink(const LinkRelAttribute&, const String& type, const KURL&, Document*);
+    bool loadLink(const LinkRelAttribute&, const String& type, const String& sizes, const KURL&, Document*);
 
 private:
     void linkLoadTimerFired(Timer<LinkLoader>*);
index 8a3a877..2e5638c 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright (C) 2008 Alp Toker <alp@atoker.com>
  * Copyright (C) Research In Motion Limited 2009. All rights reserved.
  * Copyright (C) 2011 Kris Jordan <krisjordan@gmail.com>
+ * Copyright (C) 2011 Google Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -64,30 +65,61 @@ KURL IconController::url()
     return iconURLs.isEmpty() ? KURL() : iconURLs[0].m_iconURL;
 }
 
+IconURL IconController::iconURL(IconType iconType) const
+{
+    IconURL result;
+    const Vector<IconURL>& iconURLs = m_frame->document()->iconURLs();
+    Vector<IconURL>::const_iterator iter(iconURLs.begin());
+    for (; iter != iconURLs.end(); ++iter) {
+        if (iter->m_iconType == iconType) {
+            if (result.m_iconURL.isEmpty() || !iter->m_mimeType.isEmpty())
+                result = *iter;
+        }
+    }
+
+    return result;
+}
+
 IconURLs IconController::urlsForTypes(int iconTypes)
 {
     IconURLs iconURLs;
     if (m_frame->tree() && m_frame->tree()->parent())
         return iconURLs;
-
+        
     if (iconTypes & Favicon && !appendToIconURLs(Favicon, &iconURLs))
         iconURLs.append(defaultURL(Favicon));
 
 #if ENABLE(TOUCH_ICON_LOADING)
-    bool havePrecomposedIcon = false;
+    int missedIcons = 0;
     if (iconTypes & TouchPrecomposedIcon)
-        havePrecomposedIcon = appendToIconURLs(TouchPrecomposedIcon, &iconURLs);
+        missedIcons += appendToIconURLs(TouchPrecomposedIcon, &iconURLs) ? 0:1;
 
-    bool haveTouchIcon = false;
     if (iconTypes & TouchIcon)
-        haveTouchIcon = appendToIconURLs(TouchIcon, &iconURLs);
+      missedIcons += appendToIconURLs(TouchIcon, &iconURLs) ? 0:1;
 
     // Only return the default touch icons when the both were required and neither was gotten.
-    if (iconTypes & TouchPrecomposedIcon && iconTypes & TouchIcon && !havePrecomposedIcon && !haveTouchIcon) {
+    if (missedIcons == 2) {
         iconURLs.append(defaultURL(TouchPrecomposedIcon));
         iconURLs.append(defaultURL(TouchIcon));
     }
 #endif
+
+    // Finally, append all remaining icons of this type.
+    const Vector<IconURL>& allIconURLs = m_frame->document()->iconURLs();
+    for (Vector<IconURL>::const_iterator iter = allIconURLs.begin(); iter != allIconURLs.end(); ++iter) {
+        if (!(iter->m_iconType & iconTypes))
+            continue;
+
+        int i;
+        int iconCount = iconURLs.size();
+        for (i = 0; i < iconCount; ++i) {
+            if (*iter == iconURLs.at(i))
+                break;
+        }
+        if (i == iconCount)
+            iconURLs.append(*iter);
+    }
+
     return iconURLs;
 }
 
@@ -98,11 +130,6 @@ void IconController::commitToDatabase(const KURL& icon)
     iconDatabase().setIconURLForPageURL(icon.string(), m_frame->loader()->initialRequest().url().string());
 }
 
-void IconController::setURL(const IconURL& iconURL)
-{
-    m_frame->loader()->documentLoader()->setIconURL(iconURL);
-}
-
 void IconController::startLoader()
 {
     // FIXME: We kick off the icon loader when the frame is done receiving its main resource.
@@ -218,11 +245,11 @@ void IconController::continueLoadWithDecision(IconLoadDecision iconLoadDecision)
 
 bool IconController::appendToIconURLs(IconType iconType, IconURLs* iconURLs)
 {
-    IconURL url = m_frame->document()->iconURL(iconType);
-    if (url.m_iconURL.isEmpty())
+    IconURL faviconURL = iconURL(iconType);
+    if (faviconURL.m_iconURL.isEmpty())
         return false;
 
-    iconURLs->append(url);
+    iconURLs->append(faviconURL);
     return true;
 }
 
@@ -239,18 +266,19 @@ IconURL IconController::defaultURL(IconType iconType)
     url.setHost(documentURL.host());
     if (documentURL.hasPort())
         url.setPort(documentURL.port());
+
     if (iconType == Favicon) {
         url.setPath("/favicon.ico");
-        return IconURL(url, Favicon);
+        return IconURL::defaultIconURL(url, Favicon);
     }
 #if ENABLE(TOUCH_ICON_LOADING)
     if (iconType == TouchPrecomposedIcon) {
         url.setPath("/apple-touch-icon-precomposed.png");
-        return IconURL(url, TouchPrecomposedIcon);
+        return IconURL::defaultIconURL(url, TouchPrecomposedIcon);
     }
     if (iconType == TouchIcon) {
         url.setPath("/apple-touch-icon.png");
-        return IconURL(url, TouchIcon);
+        return IconURL::defaultIconURL(url, TouchIcon);
     }
 #endif
     return IconURL();
index 90c4197..b2caba2 100644 (file)
@@ -49,9 +49,7 @@ public:
 
     KURL url();
     IconURLs urlsForTypes(int iconTypes);
-
-    // FIXME: We should inline this function into its one caller!
-    void setURL(const IconURL&);
+    IconURL iconURL(IconType) const;
 
     void startLoader();
     void stopLoader();