summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/webkit/WebCore/loader/icon/IconFetcher.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/webkit/WebCore/loader/icon/IconFetcher.cpp')
-rw-r--r--src/3rdparty/webkit/WebCore/loader/icon/IconFetcher.cpp236
1 files changed, 236 insertions, 0 deletions
diff --git a/src/3rdparty/webkit/WebCore/loader/icon/IconFetcher.cpp b/src/3rdparty/webkit/WebCore/loader/icon/IconFetcher.cpp
new file mode 100644
index 0000000..efa7e14
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/loader/icon/IconFetcher.cpp
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "IconFetcher.h"
+
+#include "Document.h"
+#include "Frame.h"
+#include "HTMLHeadElement.h"
+#include "HTMLLinkElement.h"
+#include "HTMLNames.h"
+#include "MIMETypeRegistry.h"
+#include "ResourceHandle.h"
+#include "ResourceRequest.h"
+#include "SharedBuffer.h"
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+struct IconLinkEntry {
+public:
+ enum IconType {
+ Unknown,
+ ICNS,
+ ICO,
+ };
+
+ IconLinkEntry(IconType type, const KURL& url)
+ : m_type(type)
+ , m_url(url)
+ {
+ }
+
+ IconType type() const { return m_type; }
+ const KURL& url() const { return m_url; }
+
+ SharedBuffer* buffer()
+ {
+ if (!m_buffer)
+ m_buffer = SharedBuffer::create();
+
+ return m_buffer.get();
+ }
+
+private:
+ RefPtr<SharedBuffer> m_buffer;
+ IconType m_type;
+ KURL m_url;
+};
+
+#if PLATFORM(MAC)
+static const IconLinkEntry::IconType NativeIconType = IconLinkEntry::ICNS;
+#elif PLATFORM(WIN)
+static const IconLinkEntry::IconType NativeIconType = IconLinkEntry::ICO;
+#else
+static const IconLinkEntry::IconType NativeIconType = IconLinkEntry::Unknown;
+#endif
+
+static void parseIconLink(HTMLLinkElement* link, Vector<IconLinkEntry>& entries)
+{
+ // FIXME: Parse the size attribute too.
+
+ IconLinkEntry::IconType type = IconLinkEntry::Unknown;
+ const KURL& url = link->href();
+
+ // Try to determine the file type.
+ String path = url.path();
+
+ int pos = path.reverseFind('.');
+ if (pos >= 0) {
+ String extension = path.substring(pos + 1);
+ if (equalIgnoringCase(extension, "icns"))
+ type = IconLinkEntry::ICNS;
+ else if (equalIgnoringCase(extension, "ico"))
+ type = IconLinkEntry::ICO;
+ }
+
+ entries.append(IconLinkEntry(type, url));
+}
+
+PassRefPtr<IconFetcher> IconFetcher::create(Frame* frame, IconFetcherClient* client)
+{
+ Document* document = frame->document();
+ if (!document)
+ return 0;
+
+ HTMLHeadElement* head = document->head();
+ if (!head)
+ return 0;
+
+ Vector<IconLinkEntry> entries;
+
+ for (Node* n = head; n; n = n->traverseNextNode()) {
+ if (!n->hasTagName(linkTag))
+ continue;
+
+ HTMLLinkElement* link = static_cast<HTMLLinkElement*>(n);
+ if (!link->isIcon())
+ continue;
+
+ parseIconLink(link, entries);
+ }
+
+ if (entries.isEmpty())
+ return 0;
+
+ // Check if any of the entries have the same type as the native icon type.
+
+ // FIXME: This should be way more sophisticated, and handle conversion
+ // of multisize formats for example.
+ for (unsigned i = 0; i < entries.size(); i++) {
+ const IconLinkEntry& entry = entries[i];
+ if (entry.type() == NativeIconType) {
+ RefPtr<IconFetcher> iconFetcher = adoptRef(new IconFetcher(frame, client));
+
+ iconFetcher->m_entries.append(entry);
+ iconFetcher->loadEntry();
+
+ return iconFetcher.release();
+ }
+ }
+
+ return 0;
+}
+
+IconFetcher::IconFetcher(Frame* frame, IconFetcherClient* client)
+ : m_frame(frame)
+ , m_client(client)
+ , m_currentEntry(0)
+{
+}
+
+IconFetcher::~IconFetcher()
+{
+ cancel();
+}
+
+void IconFetcher::cancel()
+{
+ if (m_handle)
+ m_handle->cancel();
+}
+
+PassRefPtr<SharedBuffer> IconFetcher::createIcon()
+{
+ ASSERT(!m_entries.isEmpty());
+
+ // For now, just return the data of the first entry.
+ return m_entries.first().buffer();
+}
+
+
+void IconFetcher::loadEntry()
+{
+ ASSERT(m_currentEntry < m_entries.size());
+ ASSERT(!m_handle);
+
+ m_handle = ResourceHandle::create(m_entries[m_currentEntry].url(), this, m_frame, false, false);
+}
+
+void IconFetcher::loadFailed()
+{
+ m_handle = 0;
+
+ m_client->finishedFetchingIcon(0);
+}
+
+void IconFetcher::didReceiveResponse(ResourceHandle* handle, const ResourceResponse& response)
+{
+ ASSERT(m_handle == handle);
+
+ int statusCode = response.httpStatusCode() / 100;
+ if (statusCode == 4 || statusCode == 5) {
+ loadFailed();
+ return;
+ }
+}
+
+void IconFetcher::didReceiveData(ResourceHandle* handle, const char* data, int length, int lengthReceived)
+{
+ ASSERT(m_handle == handle);
+
+ m_entries[m_currentEntry].buffer()->append(data, length);
+}
+
+void IconFetcher::didFinishLoading(ResourceHandle* handle)
+{
+ ASSERT(m_handle == handle);
+
+ if (m_currentEntry == m_entries.size() - 1) {
+ // We finished loading, create the icon
+ RefPtr<SharedBuffer> iconData = createIcon();
+
+ m_client->finishedFetchingIcon(iconData.release());
+ return;
+ }
+
+ // Load the next entry
+ m_currentEntry++;
+
+ loadEntry();
+}
+
+void IconFetcher::didFail(ResourceHandle* handle, const ResourceError&)
+{
+ ASSERT(m_handle == handle);
+
+ loadFailed();
+}
+
+
+} // namespace WebCore