diff options
Diffstat (limited to 'WebCore/loader')
38 files changed, 1005 insertions, 303 deletions
diff --git a/WebCore/loader/Cache.cpp b/WebCore/loader/Cache.cpp index bda91e6..bb239fc 100644 --- a/WebCore/loader/Cache.cpp +++ b/WebCore/loader/Cache.cpp @@ -35,7 +35,6 @@ #include "Image.h" #include "ResourceHandle.h" #include "SystemTime.h" -#include <stdio.h> using namespace std; @@ -89,7 +88,11 @@ static CachedResource* createResource(CachedResource::Type type, DocLoader* docL return 0; } +#ifdef ANDROID_PRELOAD_CHANGES +CachedResource* Cache::requestResource(DocLoader* docLoader, CachedResource::Type type, const KURL& url, const String* charset, bool skipCanLoadCheck, bool sendResourceLoadCallbacks, bool isPreload) +#else CachedResource* Cache::requestResource(DocLoader* docLoader, CachedResource::Type type, const KURL& url, const String* charset, bool skipCanLoadCheck, bool sendResourceLoadCallbacks) +#endif { // FIXME: Do we really need to special-case an empty URL? // Would it be better to just go on with the cache code and let it fail later? @@ -100,17 +103,28 @@ CachedResource* Cache::requestResource(DocLoader* docLoader, CachedResource::Typ CachedResource* resource = m_resources.get(url.string()); if (resource) { +#ifdef ANDROID_PRELOAD_CHANGES + if (isPreload && !resource->isPreloaded()) + return 0; +#endif if (!skipCanLoadCheck && FrameLoader::restrictAccessToLocal() && !FrameLoader::canLoad(*resource, docLoader->doc())) { Document* doc = docLoader->doc(); +#ifdef ANDROID_PRELOAD_CHANGES + if(doc && !isPreload) +#else if(doc) +#endif FrameLoader::reportLocalLoadFailed(doc->page(), resource->url()); - return 0; } } else { if (!skipCanLoadCheck && FrameLoader::restrictAccessToLocal() && !FrameLoader::canLoad(url, docLoader->doc())) { Document* doc = docLoader->doc(); +#ifdef ANDROID_PRELOAD_CHANGES + if(doc && !isPreload) +#else if(doc) +#endif FrameLoader::reportLocalLoadFailed(doc->page(), url.string()); return 0; @@ -229,7 +243,11 @@ void Cache::pruneDeadResources() // First flush all the decoded data in this queue. while (current) { CachedResource* prev = current->m_prevInAllResourcesList; +#ifdef ANDROID_PRELOAD_CHANGES + if (!current->referenced() && !current->isPreloaded() && current->isLoaded() && current->decodedSize()) { +#else if (!current->referenced() && current->isLoaded() && current->decodedSize()) { +#endif // Destroy our decoded data. This will remove us from // m_liveDecodedResources, and possibly move us to a differnt // LRU list in m_allResources. @@ -245,7 +263,11 @@ void Cache::pruneDeadResources() current = m_allResources[i].m_tail; while (current) { CachedResource* prev = current->m_prevInAllResourcesList; +#ifdef ANDROID_PRELOAD_CHANGES + if (!current->referenced() && !current->isPreloaded()) { +#else if (!current->referenced()) { +#endif remove(current); if (m_deadSize <= targetSize) @@ -253,7 +275,6 @@ void Cache::pruneDeadResources() } current = prev; } - // Shrink the vector back down so we don't waste time inspecting // empty LRU lists on future prunes. if (m_allResources[i].m_head) diff --git a/WebCore/loader/Cache.h b/WebCore/loader/Cache.h index 7e43cff..8256708 100644 --- a/WebCore/loader/Cache.h +++ b/WebCore/loader/Cache.h @@ -94,8 +94,11 @@ public: // Request resources from the cache. A load will be initiated and a cache object created if the object is not // found in the cache. +#ifdef ANDROID_PRELOAD_CHANGES + CachedResource* requestResource(DocLoader*, CachedResource::Type, const KURL& url, const String* charset = 0, bool skipCanLoadCheck = false, bool sendResourceLoadCallbacks = true, bool isPreload = false); +#else CachedResource* requestResource(DocLoader*, CachedResource::Type, const KURL& url, const String* charset = 0, bool skipCanLoadCheck = false, bool sendResourceLoadCallbacks = true); - +#endif // Sets the cache's memory capacities, in bytes. These will hold only approximately, // since the decoded cost of resources like scripts and stylesheets is not known. // - minDeadBytes: The maximum number of bytes that dead resources should consume when the cache is under pressure. @@ -143,6 +146,11 @@ public: // Function to collect cache statistics for the caches window in the Safari Debug menu. Statistics getStatistics(); +#ifdef ANDROID_INSTRUMENT + unsigned getLiveSize() { return m_liveSize; } + unsigned getDeadSize() { return m_deadSize; } +#endif + private: Cache(); ~Cache(); // Not implemented to make sure nobody accidentally calls delete -- WebCore does not delete singletons. diff --git a/WebCore/loader/CachedCSSStyleSheet.cpp b/WebCore/loader/CachedCSSStyleSheet.cpp index 36fc16e..649a16d 100644 --- a/WebCore/loader/CachedCSSStyleSheet.cpp +++ b/WebCore/loader/CachedCSSStyleSheet.cpp @@ -56,7 +56,7 @@ void CachedCSSStyleSheet::ref(CachedResourceClient *c) CachedResource::ref(c); if (!m_loading) - c->setCSSStyleSheet(m_url, m_decoder->encoding().name(), this); + c->setCSSStyleSheet(m_url, m_decoder->encoding().name(), errorOccurred() ? "" : m_sheet); } void CachedCSSStyleSheet::setEncoding(const String& chs) @@ -79,6 +79,10 @@ void CachedCSSStyleSheet::data(PassRefPtr<SharedBuffer> data, bool allDataReceiv if (m_data.get()) { m_sheet = m_decoder->decode(m_data->data(), encodedSize()); m_sheet += m_decoder->flush(); +#ifdef ANDROID_FIX + // report decoded size too + setDecodedSize(m_sheet.length() * sizeof(UChar)); +#endif } m_loading = false; checkNotify(); @@ -91,7 +95,7 @@ void CachedCSSStyleSheet::checkNotify() CachedResourceClientWalker w(m_clients); while (CachedResourceClient *c = w.next()) - c->setCSSStyleSheet(m_response.url().string(), m_decoder->encoding().name(), this); + c->setCSSStyleSheet(m_response.url().string(), m_decoder->encoding().name(), m_sheet); #if USE(LOW_BANDWIDTH_DISPLAY) // if checkNotify() is called from error(), client's setCSSStyleSheet(...) @@ -110,17 +114,4 @@ void CachedCSSStyleSheet::error() checkNotify(); } -bool CachedCSSStyleSheet::canUseSheet(bool strict) const -{ - if (errorOccurred()) - return false; - - if (!strict) - return true; - - // This check exactly matches Firefox. - String mimeType = response().mimeType(); - return mimeType.isEmpty() || equalIgnoringCase(mimeType, "text/css") || equalIgnoringCase(mimeType, "application/x-unknown-content-type"); -} - } diff --git a/WebCore/loader/CachedCSSStyleSheet.h b/WebCore/loader/CachedCSSStyleSheet.h index 382dce8..50dddc2 100644 --- a/WebCore/loader/CachedCSSStyleSheet.h +++ b/WebCore/loader/CachedCSSStyleSheet.h @@ -42,7 +42,7 @@ namespace WebCore { CachedCSSStyleSheet(DocLoader*, const String& URL, const String& charset, bool skipCanLoadCheck = false, bool sendResourceLoadCallbacks = true); virtual ~CachedCSSStyleSheet(); - const String sheetText(bool strict = true) const { return canUseSheet(strict) ? m_sheet : ""; } + const String& sheet() const { return m_sheet; } virtual void ref(CachedResourceClient*); @@ -54,9 +54,6 @@ namespace WebCore { virtual bool schedule() const { return true; } void checkNotify(); - - private: - bool canUseSheet(bool strict) const; protected: String m_sheet; diff --git a/WebCore/loader/CachedFont.cpp b/WebCore/loader/CachedFont.cpp index 703251d..169adfa 100644 --- a/WebCore/loader/CachedFont.cpp +++ b/WebCore/loader/CachedFont.cpp @@ -31,7 +31,7 @@ #include "CachedResourceClientWalker.h" #include "DOMImplementation.h" #include "FontPlatformData.h" -#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) +#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(SGL) #include "FontCustomPlatformData.h" #endif #include "TextResourceDecoder.h" @@ -96,7 +96,7 @@ void CachedFont::beginLoadIfNeeded(DocLoader* dl) bool CachedFont::ensureCustomFontData() { -#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) +#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(SGL) #if ENABLE(SVG_FONTS) ASSERT(!m_isSVGFont); #endif @@ -115,7 +115,7 @@ FontPlatformData CachedFont::platformDataFromCustomData(float size, bool bold, b if (m_externalSVGDocument) return FontPlatformData(size, bold, italic); #endif -#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) +#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(SGL) ASSERT(m_fontData); return m_fontData->fontPlatformData(static_cast<int>(size), bold, italic); #else diff --git a/WebCore/loader/CachedImage.cpp b/WebCore/loader/CachedImage.cpp index d8a43fd..f591d41 100644 --- a/WebCore/loader/CachedImage.cpp +++ b/WebCore/loader/CachedImage.cpp @@ -52,6 +52,12 @@ CachedImage::CachedImage(DocLoader* docLoader, const String& url, bool forCache) m_image = 0; m_status = Unknown; if (!docLoader || docLoader->autoLoadImages()) { +#ifdef ANDROID_BLOCK_NETWORK_IMAGE + if (docLoader && docLoader->shouldBlockNetworkImage(url)) { + m_loading = false; + return; + } +#endif m_loading = true; cache()->loader()->load(docLoader, this, true); } else @@ -186,6 +192,9 @@ inline void CachedImage::createImage() } #endif m_image = new BitmapImage(this); +#if PLATFORM(SGL) + m_image->setURL(url()); +#endif } void CachedImage::data(PassRefPtr<SharedBuffer> data, bool allDataReceived) diff --git a/WebCore/loader/CachedResource.cpp b/WebCore/loader/CachedResource.cpp index 65db74c..6c78f4b 100644 --- a/WebCore/loader/CachedResource.cpp +++ b/WebCore/loader/CachedResource.cpp @@ -39,6 +39,11 @@ CachedResource::CachedResource(const String& url, Type type, bool forCache, bool : m_url(url) , m_lastDecodedAccessTime(0) , m_sendResourceLoadCallbacks(sendResourceLoadCallbacks) +#ifdef ANDROID_PRELOAD_CHANGES + , m_preloadCount(0) + , m_preloadResult(PreloadNotReferenced) + , m_requestedFromNetworkingLayer(false) +#endif , m_inCache(forCache) , m_docLoader(0) { @@ -101,6 +106,16 @@ void CachedResource::setRequest(Request* request) void CachedResource::ref(CachedResourceClient *c) { +#ifdef ANDROID_PRELOAD_CHANGES + if (m_preloadResult == PreloadNotReferenced) { + if (isLoaded()) + m_preloadResult = PreloadReferencedWhileComplete; + else if (m_requestedFromNetworkingLayer) + m_preloadResult = PreloadReferencedWhileLoading; + else + m_preloadResult = PreloadReferenced; + } +#endif if (!referenced() && inCache()) cache()->addToLiveResourcesSize(this); m_clients.add(c); diff --git a/WebCore/loader/CachedResource.h b/WebCore/loader/CachedResource.h index ca9a756..bbfeac1 100644 --- a/WebCore/loader/CachedResource.h +++ b/WebCore/loader/CachedResource.h @@ -79,6 +79,18 @@ public: virtual void ref(CachedResourceClient*); void deref(CachedResourceClient*); bool referenced() const { return !m_clients.isEmpty(); } + +#ifdef ANDROID_PRELOAD_CHANGES + enum PreloadResult { + PreloadNotReferenced, + PreloadReferenced, + PreloadReferencedWhileLoading, + PreloadReferencedWhileComplete + }; + PreloadResult preloadResult() const { return m_preloadResult; } + void setRequestedFromNetworkingLayer() { m_requestedFromNetworkingLayer = true; } +#endif + virtual void allReferencesRemoved() {}; unsigned count() const { return m_clients.size(); } @@ -116,8 +128,12 @@ public: void setResponse(const ResourceResponse& response) { m_response = response; } const ResourceResponse& response() const { return m_response; } - + +#ifdef ANDROID_PRELOAD_CHANGES + bool canDelete() const { return !referenced() && !m_request && !m_preloadCount; } +#else bool canDelete() const { return !referenced() && !m_request; } +#endif bool isExpired() const; @@ -135,8 +151,14 @@ public: virtual void destroyDecodedData() {}; void setDocLoader(DocLoader* docLoader) { m_docLoader = docLoader; } - -protected: + +#ifdef ANDROID_PRELOAD_CHANGES + bool isPreloaded() const { return m_preloadCount; } + void increasePreloadCount() { ++m_preloadCount; } + void decreasePreloadCount() { ASSERT(m_preloadCount); --m_preloadCount; } +#endif + + protected: void setEncodedSize(unsigned); void setDecodedSize(unsigned); void didAccessDecodedData(double timeStamp); @@ -163,6 +185,13 @@ private: double m_lastDecodedAccessTime; // Used as a "thrash guard" in the cache bool m_sendResourceLoadCallbacks; + +#ifdef ANDROID_PRELOAD_CHANGES + unsigned m_preloadCount; + PreloadResult m_preloadResult; + bool m_requestedFromNetworkingLayer; +#endif + protected: bool m_inCache; bool m_loading; diff --git a/WebCore/loader/CachedResourceClient.h b/WebCore/loader/CachedResourceClient.h index 1d8d45e..48631e3 100644 --- a/WebCore/loader/CachedResourceClient.h +++ b/WebCore/loader/CachedResourceClient.h @@ -35,7 +35,6 @@ namespace XBL { namespace WebCore { - class CachedCSSStyleSheet; class CachedFont; class CachedResource; class CachedImage; @@ -65,7 +64,7 @@ namespace WebCore { // e.g., in the b/f cache or in a background tab). virtual bool willRenderImage(CachedImage*) { return false; } - virtual void setCSSStyleSheet(const String& /*URL*/, const String& /*charset*/, const CachedCSSStyleSheet*) { } + virtual void setCSSStyleSheet(const String& /*URL*/, const String& /*charset*/, const String& /*sheet*/) { } virtual void setXSLStyleSheet(const String& /*URL*/, const String& /*sheet*/) { } virtual void fontLoaded(CachedFont*) {}; diff --git a/WebCore/loader/CachedScript.cpp b/WebCore/loader/CachedScript.cpp index 42beff9..f8cde0e 100644 --- a/WebCore/loader/CachedScript.cpp +++ b/WebCore/loader/CachedScript.cpp @@ -84,6 +84,10 @@ void CachedScript::data(PassRefPtr<SharedBuffer> data, bool allDataReceived) setEncodedSize(m_data.get() ? m_data->size() : 0); if (m_data.get()) m_script = m_encoding.decode(m_data->data(), encodedSize()); +#ifdef ANDROID_FIX + // report decoded size too + setDecodedSize(m_script.length() * sizeof(UChar)); +#endif m_loading = false; checkNotify(); } diff --git a/WebCore/loader/DocLoader.cpp b/WebCore/loader/DocLoader.cpp index 9badb96..e2a2517 100644 --- a/WebCore/loader/DocLoader.cpp +++ b/WebCore/loader/DocLoader.cpp @@ -1,8 +1,10 @@ /* + This file is part of the KDE libraries + Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) Copyright (C) 2001 Dirk Mueller (mueller@kde.org) Copyright (C) 2002 Waldo Bastian (bastian@kde.org) - Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -37,6 +39,8 @@ #include "FrameLoader.h" #include "loader.h" +#define PRELOAD_DEBUG 0 + namespace WebCore { DocLoader::DocLoader(Frame *frame, Document* doc) @@ -45,6 +49,9 @@ DocLoader::DocLoader(Frame *frame, Document* doc) , m_frame(frame) , m_doc(doc) , m_requestCount(0) +#ifdef ANDROID_BLOCK_NETWORK_IMAGE + , m_blockNetworkImage(false) +#endif , m_autoLoadImages(true) , m_loadInProgress(false) , m_allowStaleResources(false) @@ -54,6 +61,9 @@ DocLoader::DocLoader(Frame *frame, Document* doc) DocLoader::~DocLoader() { +#ifdef ANDROID_PRELOAD_CHANGES + clearPreloads(); +#endif HashMap<String, CachedResource*>::iterator end = m_docResources.end(); for (HashMap<String, CachedResource*>::iterator it = m_docResources.begin(); it != end; ++it) it->second->setDocLoader(0); @@ -63,15 +73,15 @@ DocLoader::~DocLoader() void DocLoader::checkForReload(const KURL& fullURL) { if (m_allowStaleResources) - return; // Don't reload resources while pasting - - if (fullURL.isEmpty()) - return; - + return; //Don't reload resources while pasting if (m_cachePolicy == CachePolicyVerify) { if (!m_reloadedURLs.contains(fullURL.string())) { CachedResource* existing = cache()->resourceForURL(fullURL.string()); +#ifdef ANDROID_PRELOAD_CHANGES + if (existing && existing->isExpired() && !existing->isPreloaded()) { +#else if (existing && existing->isExpired()) { +#endif cache()->remove(existing); m_reloadedURLs.add(fullURL.string()); } @@ -79,9 +89,16 @@ void DocLoader::checkForReload(const KURL& fullURL) } else if ((m_cachePolicy == CachePolicyReload) || (m_cachePolicy == CachePolicyRefresh)) { if (!m_reloadedURLs.contains(fullURL.string())) { CachedResource* existing = cache()->resourceForURL(fullURL.string()); +#ifdef ANDROID_PRELOAD_CHANGES + if (existing && !existing->isPreloaded()) { +#else if (existing) +#endif cache()->remove(existing); m_reloadedURLs.add(fullURL.string()); +#ifdef ANDROID_PRELOAD_CHANGES + } +#endif } } } @@ -90,6 +107,11 @@ CachedImage* DocLoader::requestImage(const String& url) { CachedImage* resource = static_cast<CachedImage*>(requestResource(CachedResource::ImageResource, url)); if (autoLoadImages() && resource && resource->stillNeedsLoad()) { +#ifdef ANDROID_BLOCK_NETWORK_IMAGE + if (shouldBlockNetworkImage(url)) { + return resource; + } +#endif resource->setLoading(true); cache()->loader()->load(this, resource, true); } @@ -141,9 +163,13 @@ CachedXBLDocument* DocLoader::requestXBLDocument(const String& url) } #endif +#ifdef ANDROID_PRELOAD_CHANGES +CachedResource* DocLoader::requestResource(CachedResource::Type type, const String& url, const String* charset, bool skipCanLoadCheck, bool sendResourceLoadCallbacks, bool isPreload) +#else CachedResource* DocLoader::requestResource(CachedResource::Type type, const String& url, const String* charset, bool skipCanLoadCheck, bool sendResourceLoadCallbacks) +#endif { - KURL fullURL = m_doc->completeURL(url); + KURL fullURL = m_doc->completeURL(url.deprecatedString()); if (cache()->disabled()) { HashMap<String, CachedResource*>::iterator it = m_docResources.find(fullURL.string()); @@ -158,8 +184,11 @@ CachedResource* DocLoader::requestResource(CachedResource::Type type, const Stri setCachePolicy(CachePolicyReload); checkForReload(fullURL); - +#ifdef ANDROID_PRELOAD_CHANGES + CachedResource* resource = cache()->requestResource(this, type, fullURL, charset, skipCanLoadCheck, sendResourceLoadCallbacks, isPreload); +#else CachedResource* resource = cache()->requestResource(this, type, fullURL, charset, skipCanLoadCheck, sendResourceLoadCallbacks); +#endif if (resource) { m_docResources.set(resource->url(), resource); checkCacheObjectStatus(resource); @@ -182,6 +211,10 @@ void DocLoader::setAutoLoadImages(bool enable) CachedResource* resource = it->second; if (resource->type() == CachedResource::ImageResource) { CachedImage* image = const_cast<CachedImage*>(static_cast<const CachedImage*>(resource)); +#ifdef ANDROID_BLOCK_NETWORK_IMAGE + if (shouldBlockNetworkImage(image->url())) + continue; +#endif if (image->stillNeedsLoad()) cache()->loader()->load(this, image, true); @@ -189,6 +222,41 @@ void DocLoader::setAutoLoadImages(bool enable) } } +#ifdef ANDROID_BLOCK_NETWORK_IMAGE +bool DocLoader::shouldBlockNetworkImage(const String& url) const +{ + if (!m_blockNetworkImage) + return false; + + KURL kurl(url.deprecatedString()); + if (kurl.protocolIs("http") || kurl.protocolIs("https")) + return true; + + return false; +} + +void DocLoader::setBlockNetworkImage(bool block) +{ + if (block == m_blockNetworkImage) + return; + + m_blockNetworkImage = block; + + if (!m_autoLoadImages || m_blockNetworkImage) + return; + + HashMap<String, CachedResource*>::iterator end = m_docResources.end(); + for (HashMap<String, CachedResource*>::iterator it = m_docResources.begin(); it != end; ++it) { + CachedResource* resource = it->second; + if (resource->type() == CachedResource::ImageResource) { + CachedImage* image = const_cast<CachedImage*>(static_cast<const CachedImage*>(resource)); + if (image->stillNeedsLoad()) + cache()->loader()->load(this, image, true); + } + } +} +#endif + void DocLoader::setCachePolicy(CachePolicy cachePolicy) { m_cachePolicy = cachePolicy; @@ -244,4 +312,110 @@ int DocLoader::requestCount() return m_requestCount; } +#ifdef ANDROID_PRELOAD_CHANGES +void DocLoader::preload(CachedResource::Type type, const String& url, const String& charset, bool inBody) +{ + if ((inBody || type == CachedResource::ImageResource) && (!m_doc->body() || !m_doc->body()->renderer())) { + // Don't preload images or body resources before we have the first rendering. + PendingPreload pendingPreload = { type, url, charset }; + m_pendingPreloads.append(pendingPreload); + return; + } + requestPreload(type, url, charset); +} + +void DocLoader::checkForPendingPreloads() +{ + unsigned count = m_pendingPreloads.size(); + if (!count || !m_doc->body() || !m_doc->body()->renderer()) + return; + for (unsigned n = 0; n < count; ++n) { + PendingPreload& preload = m_pendingPreloads[n]; + requestPreload(preload.m_type, preload.m_url, preload.m_charset); + } + m_pendingPreloads.clear(); +} + +void DocLoader::requestPreload(CachedResource::Type type, const String& url, const String& charset) +{ + String encoding; + if (type == CachedResource::Script || type == CachedResource::CSSStyleSheet) + encoding = charset.isEmpty() ? m_doc->frame()->loader()->encoding() : charset; + + CachedResource* resource = requestResource(type, url, &encoding, false, true, true); + if (!resource || m_preloads.contains(resource)) + return; + resource->increasePreloadCount(); + m_preloads.add(resource); +#if PRELOAD_DEBUG + printf("PRELOADING %s\n", resource->url().latin1().data()); +#endif +} + +void DocLoader::clearPreloads() +{ +#if PRELOAD_DEBUG + printPreloadStats(); +#endif + ListHashSet<CachedResource*>::iterator end = m_preloads.end(); + for (ListHashSet<CachedResource*>::iterator it = m_preloads.begin(); it != end; ++it) { + CachedResource* res = *it; + res->decreasePreloadCount(); + if (res->canDelete() && !res->inCache()) + delete res; + else if (res->preloadResult() == CachedResource::PreloadNotReferenced) + cache()->remove(res); + } + m_preloads.clear(); +} + +#if PRELOAD_DEBUG +void DocLoader::printPreloadStats() +{ + unsigned scripts = 0; + unsigned scriptMisses = 0; + unsigned stylesheets = 0; + unsigned stylesheetMisses = 0; + unsigned images = 0; + unsigned imageMisses = 0; + ListHashSet<CachedResource*>::iterator end = m_preloads.end(); + for (ListHashSet<CachedResource*>::iterator it = m_preloads.begin(); it != end; ++it) { + CachedResource* res = *it; + if (res->preloadResult() == CachedResource::PreloadNotReferenced) + printf("!! UNREFERENCED PRELOAD %s\n", res->url().latin1().data()); + else if (res->preloadResult() == CachedResource::PreloadReferencedWhileComplete) + printf("HIT COMPLETE PRELOAD %s\n", res->url().latin1().data()); + else if (res->preloadResult() == CachedResource::PreloadReferencedWhileLoading) + printf("HIT LOADING PRELOAD %s\n", res->url().latin1().data()); + + if (res->type() == CachedResource::Script) { + scripts++; + if (res->preloadResult() < CachedResource::PreloadReferencedWhileLoading) + scriptMisses++; + } else if (res->type() == CachedResource::CSSStyleSheet) { + stylesheets++; + if (res->preloadResult() < CachedResource::PreloadReferencedWhileLoading) + stylesheetMisses++; + } else { + images++; + if (res->preloadResult() < CachedResource::PreloadReferencedWhileLoading) + imageMisses++; + } + + if (res->errorOccurred()) + cache()->remove(res); + + res->decreasePreloadCount(); + } + m_preloads.clear(); + + if (scripts) + printf("SCRIPTS: %d (%d hits, hit rate %d%%)\n", scripts, scripts - scriptMisses, (scripts - scriptMisses) * 100 / scripts); + if (stylesheets) + printf("STYLESHEETS: %d (%d hits, hit rate %d%%)\n", stylesheets, stylesheets - stylesheetMisses, (stylesheets - stylesheetMisses) * 100 / stylesheets); + if (images) + printf("IMAGES: %d (%d hits, hit rate %d%%)\n", images, images - imageMisses, (images - imageMisses) * 100 / images); +} +#endif +#endif // ANDROID_PRELOAD_CHANGES } diff --git a/WebCore/loader/DocLoader.h b/WebCore/loader/DocLoader.h index 68a6e50..31fb5f8 100644 --- a/WebCore/loader/DocLoader.h +++ b/WebCore/loader/DocLoader.h @@ -30,6 +30,9 @@ #include "StringHash.h" #include <wtf/HashMap.h> #include <wtf/HashSet.h> +#ifdef ANDROID_PRELOAD_CHANGES +#include <wtf/ListHashSet.h> +#endif namespace WebCore { @@ -72,6 +75,12 @@ public: bool autoLoadImages() const { return m_autoLoadImages; } void setAutoLoadImages(bool); +#ifdef ANDROID_BLOCK_NETWORK_IMAGE + bool blockNetworkImage() const { return m_blockNetworkImage; } + void setBlockNetworkImage(bool); + bool shouldBlockNetworkImage(const String& url) const; +#endif + CachePolicy cachePolicy() const { return m_cachePolicy; } void setCachePolicy(CachePolicy); @@ -92,9 +101,20 @@ public: void incrementRequestCount(); void decrementRequestCount(); int requestCount(); + +#ifdef ANDROID_PRELOAD_CHANGES + void clearPreloads(); + void preload(CachedResource::Type type, const String& url, const String& charset, bool inBody); + void checkForPendingPreloads(); + void printPreloadStats(); +#endif private: +#ifdef ANDROID_PRELOAD_CHANGES + CachedResource* requestResource(CachedResource::Type, const String& url, const String* charset = 0, bool skipCanLoadCheck = false, bool sendResourceLoadCallbacks = true, bool isPreload = false); + void requestPreload(CachedResource::Type type, const String& url, const String& charset); +#else CachedResource* requestResource(CachedResource::Type, const String& url, const String* charset = 0, bool skipCanLoadCheck = false, bool sendResourceLoadCallbacks = true); - +#endif void checkForReload(const KURL&); void checkCacheObjectStatus(CachedResource*); @@ -106,8 +126,21 @@ private: Document *m_doc; int m_requestCount; + +#ifdef ANDROID_PRELOAD_CHANGES + ListHashSet<CachedResource*> m_preloads; + struct PendingPreload { + CachedResource::Type m_type; + String m_url; + String m_charset; + }; + Vector<PendingPreload> m_pendingPreloads; +#endif //29 bits left +#ifdef ANDROID_BLOCK_NETWORK_IMAGE + bool m_blockNetworkImage : 1; +#endif bool m_autoLoadImages : 1; bool m_loadInProgress : 1; bool m_allowStaleResources : 1; diff --git a/WebCore/loader/DocumentLoader.cpp b/WebCore/loader/DocumentLoader.cpp index ba4eaf2..b90ead6 100644 --- a/WebCore/loader/DocumentLoader.cpp +++ b/WebCore/loader/DocumentLoader.cpp @@ -30,6 +30,9 @@ #include "DocumentLoader.h" #include "CachedPage.h" +#ifdef ANDROID_PRELOAD_CHANGES +#include "DocLoader.h" +#endif #include "Document.h" #include "Event.h" #include "Frame.h" @@ -123,8 +126,7 @@ static void setAllDefersLoading(const ResourceLoaderSet& loaders, bool defers) } DocumentLoader::DocumentLoader(const ResourceRequest& req, const SubstituteData& substituteData) - : RefCounted<DocumentLoader>(0) - , m_deferMainResourceDataLoad(true) + : m_deferMainResourceDataLoad(true) , m_frame(0) , m_originalRequest(req) , m_substituteData(substituteData) @@ -466,10 +468,15 @@ bool DocumentLoader::isLoadingInAPISense() const return true; if (!m_subresourceLoaders.isEmpty()) return true; - if (Document* doc = m_frame->document()) + if (Document* doc = m_frame->document()) { +#ifdef ANDROID_PRELOAD_CHANGES + if (doc->docLoader()->requestCount()) + return true; +#endif if (Tokenizer* tok = doc->tokenizer()) if (tok->processingData()) return true; + } } return frameLoader()->subframeIsLoading(); } diff --git a/WebCore/loader/FTPDirectoryDocument.cpp b/WebCore/loader/FTPDirectoryDocument.cpp index 9e1f391..beab88c 100644 --- a/WebCore/loader/FTPDirectoryDocument.cpp +++ b/WebCore/loader/FTPDirectoryDocument.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,9 +28,12 @@ #include "CharacterNames.h" #include "CString.h" +#include "Element.h" #include "HTMLNames.h" #include "HTMLTableElement.h" +#include "HTMLTableSectionElement.h" #include "HTMLTokenizer.h" +#include "KURL.h" #include "LocalizedStrings.h" #include "Logging.h" #include "FTPDirectoryParser.h" @@ -38,11 +41,12 @@ #include "Settings.h" #include "SharedBuffer.h" #include "Text.h" +#include "XMLTokenizer.h" -// On Win, the threadsafe *_r functions need to be gotten from pthreads. -#if COMPILER(MSVC) && USE(PTHREADS) -#include <pthread.h> -#endif +// On Win, the threadsafe *_r functions need to be gotten from pthreads. +#if COMPILER(MSVC) && USE(PTHREADS) +#include <pthread.h> +#endif #if PLATFORM(QT) #include <QDateTime> @@ -56,7 +60,7 @@ using namespace HTMLNames; class FTPDirectoryTokenizer : public HTMLTokenizer { public: - FTPDirectoryTokenizer(HTMLDocument*); + FTPDirectoryTokenizer(HTMLDocument* doc); virtual bool write(const SegmentedString&, bool appendData); virtual void finish(); @@ -145,7 +149,7 @@ PassRefPtr<Element> FTPDirectoryTokenizer::createTDForFilename(const String& fil { ExceptionCode ec; - String fullURL = m_doc->baseURL().string(); + String fullURL = m_doc->baseURL(); if (fullURL[fullURL.length() - 1] == '/') fullURL.append(filename); else @@ -303,7 +307,10 @@ void FTPDirectoryTokenizer::parseAndAppendOneLine(const String& inputLine) { ListResult result; - FTPEntryType typeResult = parseOneFTPLine(inputLine.latin1().data(), m_listState, result); + DeprecatedString depString = inputLine.deprecatedString(); + const char* line = depString.ascii(); + + FTPEntryType typeResult = parseOneFTPLine(line, m_listState, result); // FTPMiscEntry is a comment or usage statistic which we don't care about, and junk is invalid data - bail in these 2 cases if (typeResult == FTPMiscEntry || typeResult == FTPJunkEntry) diff --git a/WebCore/loader/FTPDirectoryParser.cpp b/WebCore/loader/FTPDirectoryParser.cpp index 96830b7..fdda0b6 100644 --- a/WebCore/loader/FTPDirectoryParser.cpp +++ b/WebCore/loader/FTPDirectoryParser.cpp @@ -30,7 +30,6 @@ #endif #include <wtf/ASCIICType.h> -#include <stdio.h> using namespace WTF; diff --git a/WebCore/loader/FormState.cpp b/WebCore/loader/FormState.cpp index 9082f0e..f5ea1e9 100644 --- a/WebCore/loader/FormState.cpp +++ b/WebCore/loader/FormState.cpp @@ -40,8 +40,7 @@ PassRefPtr<FormState> FormState::create(PassRefPtr<HTMLFormElement> form, const } FormState::FormState(PassRefPtr<HTMLFormElement> form, const HashMap<String, String>& values, PassRefPtr<Frame> sourceFrame) - : RefCounted<FormState>(0) - , m_form(form) + : m_form(form) , m_values(values) , m_sourceFrame(sourceFrame) { diff --git a/WebCore/loader/FrameLoader.cpp b/WebCore/loader/FrameLoader.cpp index d81fee0..b0b4f90 100644 --- a/WebCore/loader/FrameLoader.cpp +++ b/WebCore/loader/FrameLoader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. * Copyright (C) 2007 Trolltech ASA * * Redistribution and use in source and binary forms, with or without @@ -112,6 +112,11 @@ using namespace EventNames; const unsigned int cMaxPendingSourceLengthInLowBandwidthDisplay = 128 * 1024; #endif +#ifdef ANDROID_INSTRUMENT +static double sCurrentTime = 0.0; +static uint32_t sCurrentThreadTime = 0; +#endif + struct FormSubmission { const char* action; String url; @@ -412,9 +417,13 @@ bool FrameLoader::requestFrame(HTMLFrameOwnerElement* ownerElement, const String // Support for <frame src="javascript:string"> KURL scriptURL; KURL url; +#ifdef ANDROID_JAVASCRIPT_SECURITY if (protocolIs(urlString, "javascript")) { - scriptURL = KURL(urlString); - url = blankURL(); +#else + if (urlString.startsWith("javascript:", false)) { +#endif + scriptURL = urlString.deprecatedString(); + url = "about:blank"; } else url = completeURL(urlString); @@ -472,7 +481,7 @@ Frame* FrameLoader::loadSubframe(HTMLFrameOwnerElement* ownerElement, const KURL // FIXME: In this case the Frame will have finished loading before // it's being added to the child list. It would be a good idea to // create the child first, then invoke the loader separately. - if (url.isEmpty() || url == blankURL()) { + if (url.isEmpty() || url == "about:blank") { frame->loader()->completed(); frame->loader()->checkCompleted(); } @@ -501,7 +510,12 @@ void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<F if (u.isEmpty()) return; +#ifdef ANDROID_JAVASCRIPT_SECURITY if (u.protocolIs("javascript")) { +#else + DeprecatedString urlString = u.deprecatedString(); + if (urlString.startsWith("javascript:", false)) { +#endif m_isExecutingJavaScriptFormAction = true; executeIfJavaScriptURL(u, false, false); m_isExecutingJavaScriptFormAction = false; @@ -531,11 +545,11 @@ void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<F String query = u.query(); if (!query.isEmpty()) query.append('&'); - u.setQuery(query + body); + u.setQuery((query + body).deprecatedString()); } if (strcmp(action, "GET") == 0) { - u.setQuery(formData->flattenToString()); + u.setQuery(formData->flattenToString().deprecatedString()); } else { if (!isMailtoForm) frameRequest.resourceRequest().setHTTPBody(formData.get()); @@ -592,6 +606,7 @@ void FrameLoader::stopLoading(bool sendUnload) XMLHttpRequest::cancelRequests(doc); +// ANDROID_FIX ENABLE(DATABASE) missing from WebKit sources #if ENABLE(DATABASE) doc->stopDatabases(); #endif @@ -653,16 +668,16 @@ KURL FrameLoader::iconURL() { // If this isn't a top level frame, return nothing if (m_frame->tree() && m_frame->tree()->parent()) - return KURL(); - + return ""; + // If we have an iconURL from a Link element, return that if (m_frame->document() && !m_frame->document()->iconURL().isEmpty()) - return KURL(m_frame->document()->iconURL()); - + return m_frame->document()->iconURL().deprecatedString(); + // Don't return a favicon iconURL unless we're http or https - if (!m_URL.protocolIs("http") && !m_URL.protocolIs("https")) - return KURL(); - + if (m_URL.protocol() != "http" && m_URL.protocol() != "https") + return ""; + KURL url; url.setProtocol(m_URL.protocol()); url.setHost(m_URL.host()); @@ -691,7 +706,7 @@ bool FrameLoader::didOpenURL(const KURL& url) m_frame->setJSDefaultStatusBarText(String()); m_URL = url; - if ((m_URL.protocolIs("http") || m_URL.protocolIs("https")) && !m_URL.host().isEmpty() && m_URL.path().isEmpty()) + if (m_URL.protocol().startsWith("http") && !m_URL.host().isEmpty() && m_URL.path().isEmpty()) m_URL.setPath("/"); m_workingURL = m_URL; @@ -713,16 +728,20 @@ void FrameLoader::didExplicitOpen() // Cancelling redirection here works for all cases because document.open // implicitly precedes document.write. cancelRedirection(); - if (m_frame->document()->url() != blankURL()) + if (m_frame->document()->url() != "about:blank") m_URL = m_frame->document()->url(); } bool FrameLoader::executeIfJavaScriptURL(const KURL& url, bool userGesture, bool replaceDocument) { +#ifdef ANDROID_JAVASCRIPT_SECURITY if (!url.protocolIs("javascript")) +#else + if (!url.deprecatedString().startsWith("javascript:", false)) +#endif return false; - String script = decodeURLEscapeSequences(url.string().substring(strlen("javascript:"))); + String script = KURL::decode_string(url.deprecatedString().mid(strlen("javascript:"))); JSValue* result = executeScript(script, userGesture); String scriptResult; @@ -862,7 +881,7 @@ void FrameLoader::receivedFirstData() if (url.isEmpty()) url = m_URL.string(); else - url = m_frame->document()->completeURL(url).string(); + url = m_frame->document()->completeURL(url); scheduleHTTPRedirection(delay, url); } @@ -900,22 +919,23 @@ void FrameLoader::begin(const KURL& url, bool dispatch, SecurityOrigin* origin) m_isDisplayingInitialEmptyDocument = m_creatingInitialEmptyDocument; KURL ref(url); - ref.setUser(String()); - ref.setPass(String()); - ref.setRef(String()); + ref.setUser(DeprecatedString()); + ref.setPass(DeprecatedString()); + ref.setRef(DeprecatedString()); m_outgoingReferrer = ref.string(); m_URL = url; - KURL baseURL; + KURL baseurl; + if (!m_URL.isEmpty()) - baseURL = m_URL; + baseurl = m_URL; RefPtr<Document> document = DOMImplementation::instance()->createDocument(m_responseMIMEType, m_frame, m_frame->inViewSourceMode()); m_frame->setDocument(document); - document->setURL(m_URL); + document->setURL(m_URL.deprecatedString()); // We prefer m_baseURL over m_URL because m_URL changes when we are // about to load a new page. - document->setBaseURL(baseURL); + document->setBaseURL(baseurl.deprecatedString()); if (m_decoder) document->setDecoder(m_decoder.get()); if (forcedSecurityOrigin) @@ -925,6 +945,9 @@ void FrameLoader::begin(const KURL& url, bool dispatch, SecurityOrigin* origin) Settings* settings = document->settings(); document->docLoader()->setAutoLoadImages(settings && settings->loadsImagesAutomatically()); +#ifdef ANDROID_BLOCK_NETWORK_IMAGE + document->docLoader()->setBlockNetworkImage(settings && settings->blockNetworkImage()); +#endif #if FRAME_LOADS_USER_STYLESHEET KURL userStyleSheet = settings ? settings->userStyleSheetLocation() : KURL(); @@ -992,6 +1015,7 @@ void FrameLoader::write(const char* str, int len, bool flush) if (!m_receivedData) { m_receivedData = true; + m_frame->document()->determineParseMode(decoded); if (m_decoder->encoding().usesVisualOrdering()) m_frame->document()->setVisuallyOrdered(); m_frame->document()->recalcStyle(Node::Force); @@ -1165,7 +1189,9 @@ void FrameLoader::restoreDocumentState() switch (loadType()) { case FrameLoadTypeReload: +#ifndef ANDROID_HISTORY_CLIENT case FrameLoadTypeReloadAllowingStaleData: +#endif case FrameLoadTypeSame: case FrameLoadTypeReplace: break; @@ -1174,6 +1200,9 @@ void FrameLoader::restoreDocumentState() case FrameLoadTypeIndexedBackForward: case FrameLoadTypeRedirectWithLockedHistory: case FrameLoadTypeStandard: +#ifdef ANDROID_HISTORY_CLIENT + case FrameLoadTypeReloadAllowingStaleData: +#endif itemToRestore = m_currentHistoryItem.get(); } @@ -1186,19 +1215,21 @@ void FrameLoader::restoreDocumentState() void FrameLoader::gotoAnchor() { // If our URL has no ref, then we have no place we need to jump to. - // OTOH If CSS target was set previously, we want to set it to 0, recalc + // OTOH if css target was set previously, we want to set it to 0, recalc // and possibly repaint because :target pseudo class may have been - // set (see bug 11321). - if (!m_URL.hasRef() && !(m_frame->document() && m_frame->document()->getCSSTarget())) - return; - - String ref = m_URL.ref(); - if (gotoAnchor(ref)) + // set(See bug 11321) + if (!m_URL.hasRef() && + !(m_frame->document() && m_frame->document()->getCSSTarget())) return; - // Try again after decoding the ref, based on the document's encoding. - if (m_decoder) - gotoAnchor(decodeURLEscapeSequences(ref, m_decoder->encoding())); + DeprecatedString ref = m_URL.encodedHtmlRef(); + if (!gotoAnchor(ref)) { + // Can't use htmlRef() here because it doesn't know which encoding to use to decode. + // Decoding here has to match encoding in completeURL, which means it has to use the + // page's encoding rather than UTF-8. + if (m_decoder) + gotoAnchor(KURL::decode_string(ref, m_decoder->encoding())); + } } void FrameLoader::finishedParsing() @@ -1325,7 +1356,7 @@ String FrameLoader::baseTarget() const KURL FrameLoader::completeURL(const String& url) { ASSERT(m_frame->document()); - return m_frame->document()->completeURL(url); + return m_frame->document()->completeURL(url).deprecatedString(); } void FrameLoader::scheduleHTTPRedirection(double delay, const String& url) @@ -1342,8 +1373,8 @@ void FrameLoader::scheduleLocationChange(const String& url, const String& referr { // If the URL we're going to navigate to is the same as the current one, except for the // fragment part, we don't need to schedule the location change. - KURL parsedURL(url); - if (parsedURL.hasRef() && equalIgnoringRef(m_URL, parsedURL)) { + KURL u(url.deprecatedString()); + if (u.hasRef() && equalIgnoringRef(m_URL, u)) { changeLocation(url, referrer, lockHistory, wasUserGesture); return; } @@ -1694,6 +1725,14 @@ void FrameLoader::handleFallbackContent() void FrameLoader::provisionalLoadStarted() { +#ifdef ANDROID_INSTRUMENT + if (!m_frame->tree()->parent()) { + m_frame->resetTimeCounter(); + sCurrentTime = currentTime(); + sCurrentThreadTime = get_thread_msec(); + } +#endif + Page* page = m_frame->page(); // this is used to update the current history item @@ -1769,7 +1808,7 @@ bool FrameLoader::canCachePage() // they would need to be destroyed and then recreated, and there is no way that we can recreate // the right NPObjects. See <rdar://problem/5197041> for more information. && !m_containsPlugIns - && !m_URL.protocolIs("https") + && !m_URL.protocol().startsWith("https") && m_frame->document() && !m_frame->document()->applets()->length() && !m_frame->document()->hasWindowEventListener(unloadEvent) @@ -1794,15 +1833,15 @@ void FrameLoader::updatePolicyBaseURL() if (m_frame->tree()->parent() && m_frame->tree()->parent()->document()) setPolicyBaseURL(m_frame->tree()->parent()->document()->policyBaseURL()); else - setPolicyBaseURL(m_URL); + setPolicyBaseURL(m_URL.string()); } -void FrameLoader::setPolicyBaseURL(const KURL& url) +void FrameLoader::setPolicyBaseURL(const String& s) { if (m_frame->document()) - m_frame->document()->setPolicyBaseURL(url); + m_frame->document()->setPolicyBaseURL(s); for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) - child->loader()->setPolicyBaseURL(url); + child->loader()->setPolicyBaseURL(s); } // This does the same kind of work that FrameLoader::openURL does, except it relies on the fact @@ -1846,7 +1885,7 @@ void FrameLoader::startRedirectionTimer() case ScheduledRedirection::redirection: case ScheduledRedirection::locationChange: case ScheduledRedirection::locationChangeDuringLoad: - clientRedirected(KURL(m_scheduledRedirection->url), + clientRedirected(m_scheduledRedirection->url.deprecatedString(), m_scheduledRedirection->delay, currentTime() + m_redirectionTimer.nextFireInterval(), m_scheduledRedirection->lockHistory, @@ -1945,7 +1984,7 @@ void FrameLoader::load(const FrameLoadRequest& request, bool lockHistory, bool u referrer = m_outgoingReferrer; ASSERT(frame()->document()); - if (url.protocolIs("file")) { + if (url.deprecatedString().startsWith("file:", false)) { if (!canLoad(url, frame()->document()) && !canLoad(url, referrer)) { FrameLoader::reportLocalLoadFailed(m_frame->page(), url.string()); return; @@ -1970,23 +2009,41 @@ void FrameLoader::load(const FrameLoadRequest& request, bool lockHistory, bool u if (submitForm && !formValues.isEmpty()) formState = FormState::create(submitForm, formValues, m_frame); +#ifdef ANDROID_USER_GESTURE + load(request.resourceRequest().url(), referrer, loadType, + request.frameName(), event, formState.release(), userGesture); +#else load(request.resourceRequest().url(), referrer, loadType, request.frameName(), event, formState.release()); +#endif } else +#ifdef ANDROID_USER_GESTURE + post(request.resourceRequest().url(), referrer, request.frameName(), + request.resourceRequest().httpBody(), request.resourceRequest().httpContentType(), event, submitForm, formValues, userGesture); +#else post(request.resourceRequest().url(), referrer, request.frameName(), request.resourceRequest().httpBody(), request.resourceRequest().httpContentType(), event, submitForm, formValues); +#endif if (targetFrame && targetFrame != m_frame) if (Page* page = targetFrame->page()) page->chrome()->focus(); } +#ifdef ANDROID_USER_GESTURE +void FrameLoader::load(const KURL& newURL, const String& referrer, FrameLoadType newLoadType, + const String& frameName, Event* event, PassRefPtr<FormState> formState, bool userGesture) +#else void FrameLoader::load(const KURL& newURL, const String& referrer, FrameLoadType newLoadType, const String& frameName, Event* event, PassRefPtr<FormState> formState) +#endif { bool isFormSubmission = formState; ResourceRequest request(newURL); +#ifdef ANDROID_USER_GESTURE + request.setUserGesture(userGesture); +#endif if (!referrer.isEmpty()) request.setHTTPReferrer(referrer); addExtraFieldsToRequest(request, true, event || isFormSubmission); @@ -1999,7 +2056,11 @@ void FrameLoader::load(const KURL& newURL, const String& referrer, FrameLoadType if (!frameName.isEmpty()) { if (Frame* targetFrame = findFrameForNavigation(frameName)) +#ifdef ANDROID_USER_GESTURE + targetFrame->loader()->load(newURL, referrer, newLoadType, String(), event, formState, userGesture); +#else targetFrame->loader()->load(newURL, referrer, newLoadType, String(), event, formState); +#endif else checkNewWindowPolicy(action, request, formState, frameName); return; @@ -2013,18 +2074,18 @@ void FrameLoader::load(const KURL& newURL, const String& referrer, FrameLoadType // exactly the same so pages with '#' links and DHTML side effects // work properly. if (!isFormSubmission - && newLoadType != FrameLoadTypeRedirectWithLockedHistory - && newLoadType != FrameLoadTypeReload - && newLoadType != FrameLoadTypeSame - && !shouldReload(newURL, url()) - && !m_frame->isFrameSet()) { + && newLoadType != FrameLoadTypeReload + && newLoadType != FrameLoadTypeSame + && !shouldReload(newURL, url()) + // We don't want to just scroll if a link from within a + // frameset is trying to reload the frameset into _top. + && !m_frame->isFrameSet()) { // Just do anchor navigation within the existing content. // We don't do this if we are submitting a form, explicitly reloading, // currently displaying a frameset, or if the new URL does not have a fragment. - - // These rules were originally based on what KHTML was doing in KHTMLPart::openURL. + // These rules are based on what KHTML was doing in KHTMLPart::openURL. // FIXME: What about load types other than Standard and Reload? @@ -2033,19 +2094,22 @@ void FrameLoader::load(const KURL& newURL, const String& referrer, FrameLoadType checkNavigationPolicy(request, oldDocumentLoader.get(), formState, callContinueFragmentScrollAfterNavigationPolicy, this); } else { - // must grab m_quickRedirectComing now, since this load may stop the previous load and clear this flag. + // must grab this now, since this load may stop the previous load and clear this flag bool isRedirect = m_quickRedirectComing; load(request, action, newLoadType, formState); if (isRedirect) { m_quickRedirectComing = false; if (m_provisionalDocumentLoader) m_provisionalDocumentLoader->setIsClientRedirect(true); - } else if (sameURL) { +#ifdef ANDROID_HISTORY_CLIENT + } else if (sameURL && (newLoadType != FrameLoadTypeReloadAllowingStaleData)) +#else + } else if (sameURL) +#endif // Example of this case are sites that reload the same URL with a different cookie // driving the generated content, or a master frame with links that drive a target // frame, where the user has clicked on the same link repeatedly. m_loadType = FrameLoadTypeSame; - } } } @@ -2172,8 +2236,8 @@ void FrameLoader::reportLocalLoadFailed(const Page* page, const String& url) bool FrameLoader::shouldHideReferrer(const KURL& url, const String& referrer) { - bool referrerIsSecureURL = protocolIs(referrer, "https"); - bool referrerIsWebURL = referrerIsSecureURL || protocolIs(referrer, "http"); + bool referrerIsSecureURL = referrer.startsWith("https:", false); + bool referrerIsWebURL = referrerIsSecureURL || referrer.startsWith("http:", false); if (!referrerIsWebURL) return true; @@ -2181,7 +2245,7 @@ bool FrameLoader::shouldHideReferrer(const KURL& url, const String& referrer) if (!referrerIsSecureURL) return false; - bool URLIsSecureURL = url.protocolIs("https"); + bool URLIsSecureURL = url.deprecatedString().startsWith("https:", false); return !URLIsSecureURL; } @@ -2354,12 +2418,11 @@ bool FrameLoader::shouldAllowNavigation(Frame* targetFrame) const return true; } - Settings* settings = targetFrame->settings(); - if (settings && !settings->privateBrowsingEnabled()) { + if (!targetFrame->settings()->privateBrowsingEnabled()) { Document* targetDocument = targetFrame->document(); // FIXME: this error message should contain more specifics of why the navigation change is not allowed. String message = String::format("Unsafe JavaScript attempt to initiate a navigation change for frame with URL %s from frame with URL %s.\n", - targetDocument->url().string().utf8().data(), activeDocument->url().string().utf8().data()); + targetDocument->url().utf8().data(), activeDocument->url().utf8().data()); if (KJS::Interpreter::shouldPrintExceptions()) printf("%s", message.utf8().data()); @@ -2559,7 +2622,7 @@ void FrameLoader::commitProvisionalLoad(PassRefPtr<CachedPage> prpCachedPage) if (url.isEmpty()) url = pdl->responseURL(); if (url.isEmpty()) - url = blankURL(); + url = "about:blank"; didOpenURL(url); } @@ -2748,7 +2811,7 @@ void FrameLoader::open(CachedPage& cachedPage) KURL url = cachedPage.url(); - if ((url.protocolIs("http") || url.protocolIs("https")) && !url.host().isEmpty() && url.path().isEmpty()) + if (url.protocol().startsWith("http") && !url.host().isEmpty() && url.path().isEmpty()) url.setPath("/"); m_URL = url; @@ -2846,7 +2909,7 @@ void FrameLoader::didReceiveServerRedirectForProvisionalLoadForFrame() void FrameLoader::finishedLoadingDocument(DocumentLoader* loader) { -#if PLATFORM(WIN) +#if PLATFORM(WIN) || defined(ANDROID) if (!m_creatingInitialEmptyDocument) #endif m_client->finishedLoading(loader); @@ -2984,6 +3047,14 @@ void FrameLoader::checkLoadCompleteForThisFrame() if (Page* page = m_frame->page()) page->progress()->progressCompleted(m_frame); + +#ifdef ANDROID_INSTRUMENT + if (!m_frame->tree()->parent()) { + m_frame->reportTimeCounter(m_URL.deprecatedString(), + static_cast<int>((currentTime() - sCurrentTime) * 1000), + (get_thread_msec() - sCurrentThreadTime)); + } +#endif return; } @@ -3031,7 +3102,13 @@ void FrameLoader::continueLoadAfterWillSubmitForm(PolicyAction) void FrameLoader::didFirstLayout() { if (Page* page = m_frame->page()) +#ifdef ANDROID_HISTORY_CLIENT + // this should match the logic in FrameStateCommittedPage, so that we + // can restore the scroll position and view state as early as possible + if ((isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload) && page->backForwardList()) +#else if (isBackForwardLoadType(m_loadType) && page->backForwardList()) +#endif restoreScrollPositionAndViewState(); m_firstLayoutDone = true; @@ -3150,6 +3227,9 @@ String FrameLoader::userAgent(const KURL& url) const void FrameLoader::tokenizerProcessedData() { +// ASSERT(m_frame->page()); +// ASSERT(m_frame->document()); + checkCompleted(); } @@ -3228,8 +3308,13 @@ void FrameLoader::committedLoad(DocumentLoader* loader, const char* data, int le m_client->committedLoad(loader, data, length); } +#ifdef ANDROID_USER_GESTURE +void FrameLoader::post(const KURL& url, const String& referrer, const String& frameName, PassRefPtr<FormData> formData, + const String& contentType, Event* event, HTMLFormElement* form, const HashMap<String, String>& formValues, bool userGesture) +#else void FrameLoader::post(const KURL& url, const String& referrer, const String& frameName, PassRefPtr<FormData> formData, const String& contentType, Event* event, HTMLFormElement* form, const HashMap<String, String>& formValues) +#endif { // When posting, use the NSURLRequestReloadIgnoringCacheData load flag. // This prevents a potential bug which may cause a page with a form that uses itself @@ -3238,6 +3323,9 @@ void FrameLoader::post(const KURL& url, const String& referrer, const String& fr // FIXME: Where's the code that implements what the comment above says? ResourceRequest request(url); +#ifdef ANDROID_USER_GESTURE + request.setUserGesture(userGesture); +#endif addExtraFieldsToRequest(request, true, true); if (!referrer.isEmpty()) @@ -3261,6 +3349,32 @@ void FrameLoader::post(const KURL& url, const String& referrer, const String& fr load(request, action, FrameLoadTypeStandard, formState.release()); } +#ifdef ANDROID_FIX +// Fix android bug http://b/issue?id=1131683 and +// webkit bug https://bugs.webkit.org/show_bug.cgi?id=18674 +// when doing history navigation for subframe, it needs a way to do post. +// The following code is similar to loadItem(HistoryItem* item, FrameLoadType loadType) +// when there is form data. +void FrameLoader::postFromHistory(const KURL& url, PassRefPtr<FormData> formData, + const String& contentType, const String& referrer, FrameLoadType loadType) +{ + ASSERT(isBackForwardLoadType(loadType) || + loadType == FrameLoadTypeReload || + loadType == FrameLoadTypeReloadAllowingStaleData); + + ResourceRequest request(url); + addExtraFieldsToRequest(request, true, true); + + request.setHTTPMethod("POST"); + request.setHTTPBody(formData); + request.setHTTPContentType(contentType); + request.setHTTPReferrer(referrer); + + NavigationAction action(url, loadType, false); + load(request, action, loadType, 0); +} +#endif + bool FrameLoader::isReloading() const { return documentLoader()->request().cachePolicy() == ReloadIgnoringCacheData; @@ -3394,8 +3508,9 @@ void FrameLoader::callContinueFragmentScrollAfterNavigationPolicy(void* argument void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue) { - // FIXME: Some functions check m_quickRedirectComing, and others check for - // FrameLoadTypeRedirectWithLockedHistory; need to unify these. + // FIXME: + // some functions check m_quickRedirectComing, and others check for + // FrameLoadTypeRedirectWithLockedHistory. bool isRedirect = m_quickRedirectComing || m_policyLoadType == FrameLoadTypeRedirectWithLockedHistory; m_quickRedirectComing = false; @@ -3422,18 +3537,14 @@ void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequ scrollToAnchor(url); - if (!isRedirect) { + if (!isRedirect) // This will clear previousItem from the rest of the frame tree that didn't // doing any loading. We need to make a pass on this now, since for anchor nav // we'll not go through a real load and reach Completed state. checkLoadComplete(); - } m_client->dispatchDidChangeLocationWithinPage(); m_client->didFinishLoad(); - - if (m_scheduledRedirection && !m_redirectionTimer.isActive()) - startRedirectionTimer(); } void FrameLoader::opened() @@ -3826,9 +3937,9 @@ PassRefPtr<HistoryItem> FrameLoader::createHistoryItem(bool useOriginal) // Later we may want to learn to live with nil for URL. // See bug 3368236 and related bugs for more information. if (url.isEmpty()) - url = blankURL(); + url = KURL("about:blank"); if (originalURL.isEmpty()) - originalURL = blankURL(); + originalURL = KURL("about:blank"); RefPtr<HistoryItem> item = new HistoryItem(url, m_frame->tree()->name(), m_frame->tree()->parent() ? m_frame->tree()->parent()->tree()->name() : "", docLoader ? docLoader->title() : ""); item->setOriginalURLString(originalURL.string()); @@ -3981,7 +4092,7 @@ void FrameLoader::saveDocumentState() ASSERT(document); if (document && item->isCurrentDocument(document)) { - LOG(Loading, "WebCoreLoading %s: saving form state to %p", m_frame->tree()->name().string().utf8().data(), item); + LOG(Loading, "WebCoreLoading %s: saving form state to %p", m_frame->tree()->name().domString().utf8().data(), item); item->setDocumentState(document->formElementsState()); } } @@ -4227,41 +4338,40 @@ bool FrameLoader::childFramesMatchItem(HistoryItem* item) const return true; } -void FrameLoader::updateGlobalHistory() +void FrameLoader::addHistoryForCurrentLocation() { - Settings* settings = m_frame->settings(); - if (!settings) - return; - if (settings->privateBrowsingEnabled()) - return; - const KURL& url = documentLoader()->urlForHistory(); - if (url.isEmpty()) - return; - m_client->updateGlobalHistory(url); + if (!m_frame->settings()->privateBrowsingEnabled()) { + // FIXME: <rdar://problem/4880065> - This will be a hook into the WebCore global history, and this loader/client call will be removed + m_client->updateGlobalHistoryForStandardLoad(documentLoader()->urlForHistory()); + } + addBackForwardItemClippedAtTarget(true); } void FrameLoader::updateHistoryForStandardLoad() { LOG(History, "WebCoreHistory: Updating History for Standard Load in frame %s", documentLoader()->url().string().ascii().data()); - // If the navigation occured during load and this is a subframe, update the current - // history item rather than adding a new one. <rdar://problem/5333496> - bool frameNavigationDuringLoad = false; + bool frameNavigationOnLoad = false; + + // if the navigation occured during on load and this is a subframe + // update the current history item rather than adding a new one + // <rdar://problem/5333496> if (m_navigationDuringLoad) { HTMLFrameOwnerElement* owner = m_frame->ownerElement(); - frameNavigationDuringLoad = owner && !owner->createdByParser(); - m_navigationDuringLoad = false; + frameNavigationOnLoad = owner && !owner->createdByParser(); } - - if (!frameNavigationDuringLoad && !documentLoader()->isClientRedirect()) { + + if (!frameNavigationOnLoad && !documentLoader()->isClientRedirect()) { if (!documentLoader()->urlForHistory().isEmpty()) - addBackForwardItemClippedAtTarget(true); + addHistoryForCurrentLocation(); } else if (documentLoader()->unreachableURL().isEmpty() && m_currentHistoryItem) { m_currentHistoryItem->setURL(documentLoader()->url()); m_currentHistoryItem->setFormInfoFromRequest(documentLoader()->request()); } - - updateGlobalHistory(); + + // reset navigation during on load since we no longer + // need it past thsi point + m_navigationDuringLoad = false; } void FrameLoader::updateHistoryForClientRedirect() @@ -4277,8 +4387,6 @@ void FrameLoader::updateHistoryForClientRedirect() m_currentHistoryItem->clearDocumentState(); m_currentHistoryItem->clearScrollPoint(); } - - // FIXME: Should we call updateGlobalHistory here? } void FrameLoader::updateHistoryForBackForwardNavigation() @@ -4290,8 +4398,6 @@ void FrameLoader::updateHistoryForBackForwardNavigation() // Must grab the current scroll position before disturbing it saveScrollPositionAndViewStateToItem(m_previousHistoryItem.get()); - - // FIXME: Should we call updateGlobalHistory here? } void FrameLoader::updateHistoryForReload() @@ -4312,7 +4418,9 @@ void FrameLoader::updateHistoryForReload() m_currentHistoryItem->setURL(documentLoader()->requestURL()); } - updateGlobalHistory(); + // FIXME: <rdar://problem/4880065> - This will be a hook into the WebCore global history, and this loader/client call will be removed + // Update the last visited time. Mostly interesting for URL autocompletion statistics. + m_client->updateGlobalHistoryForReload(documentLoader()->originalURL()); } void FrameLoader::updateHistoryForRedirectWithLockedHistory() @@ -4324,8 +4432,15 @@ void FrameLoader::updateHistoryForRedirectWithLockedHistory() if (documentLoader()->isClientRedirect()) { if (!m_currentHistoryItem && !m_frame->tree()->parent()) - addBackForwardItemClippedAtTarget(true); + addHistoryForCurrentLocation(); if (m_currentHistoryItem) { +#ifdef ANDROID_FIX + if (m_currentHistoryItem->formData()) { + m_currentHistoryItem->setOriginalFormInfo(m_currentHistoryItem->formData()->copy(), + m_currentHistoryItem->formContentType(), + m_currentHistoryItem->formReferrer()); + } +#endif m_currentHistoryItem->setURL(documentLoader()->url()); m_currentHistoryItem->setFormInfoFromRequest(documentLoader()->request()); } @@ -4334,8 +4449,6 @@ void FrameLoader::updateHistoryForRedirectWithLockedHistory() if (parentFrame && parentFrame->loader()->m_currentHistoryItem) parentFrame->loader()->m_currentHistoryItem->addChildItem(createHistoryItem(true)); } - - updateGlobalHistory(); } void FrameLoader::updateHistoryForCommit() @@ -4579,7 +4692,7 @@ Widget* FrameLoader::createJavaAppletWidget(const IntSize& size, Element* elemen } if (baseURLString.isEmpty()) - baseURLString = m_frame->document()->baseURL().string(); + baseURLString = m_frame->document()->baseURL(); KURL baseURL = completeURL(baseURLString); return m_client->createJavaAppletWidget(size, element, baseURL, paramNames, paramValues); @@ -4796,8 +4909,8 @@ void FrameLoader::switchOutLowBandwidthDisplayIfReady() RefPtr<Document> newDoc = DOMImplementation::instance()-> createDocument(m_responseMIMEType, m_frame, m_frame->inViewSourceMode()); m_frame->setDocument(newDoc); - newDoc->setURL(m_URL); - newDoc->setBaseURL(m_URL); + newDoc->setURL(m_URL.deprecatedString()); + newDoc->setBaseURL(m_URL.deprecatedString()); if (m_decoder) newDoc->setDecoder(m_decoder.get()); restoreDocumentState(); @@ -4818,6 +4931,7 @@ void FrameLoader::switchOutLowBandwidthDisplayIfReady() if (m_pendingSourceInLowBandwidthDisplay.length()) { // set cachePolicy to Cache to use the loaded resource newDoc->docLoader()->setCachePolicy(CachePolicyCache); + newDoc->determineParseMode(m_pendingSourceInLowBandwidthDisplay); if (m_decoder->encoding().usesVisualOrdering()) newDoc->setVisuallyOrdered(); newDoc->recalcStyle(Node::Force); diff --git a/WebCore/loader/FrameLoader.h b/WebCore/loader/FrameLoader.h index 182f1c3..a8a9735 100644 --- a/WebCore/loader/FrameLoader.h +++ b/WebCore/loader/FrameLoader.h @@ -144,11 +144,23 @@ namespace WebCore { void load(const KURL&, Event*); void load(const FrameLoadRequest&, bool lockHistory, bool userGesture, Event*, HTMLFormElement*, const HashMap<String, String>& formValues); +#ifdef ANDROID_USER_GESTURE + void load(const KURL&, const String& referrer, FrameLoadType, const String& target, + Event*, PassRefPtr<FormState>, bool userGesture); + void post(const KURL&, const String& referrer, const String& target, + PassRefPtr<FormData>, const String& contentType, + Event*, HTMLFormElement*, const HashMap<String, String>& formValues, bool userGesture); +#else void load(const KURL&, const String& referrer, FrameLoadType, const String& target, Event*, PassRefPtr<FormState>); void post(const KURL&, const String& referrer, const String& target, PassRefPtr<FormData>, const String& contentType, Event*, HTMLFormElement*, const HashMap<String, String>& formValues); +#endif +#ifdef ANDROID_FIX + void postFromHistory(const KURL& url, PassRefPtr<FormData> formData, + const String& contentType, const String& referrer, FrameLoadType loadType); +#endif void load(const ResourceRequest&); void load(const ResourceRequest&, const SubstituteData&); @@ -449,6 +461,7 @@ namespace WebCore { void recursiveGoToItem(HistoryItem*, HistoryItem*, FrameLoadType); bool childFramesMatchItem(HistoryItem*) const; + void addHistoryForCurrentLocation(); void updateHistoryForBackForwardNavigation(); void updateHistoryForReload(); void updateHistoryForStandardLoad(); @@ -456,8 +469,6 @@ namespace WebCore { void updateHistoryForClientRedirect(); void updateHistoryForCommit(); - void updateGlobalHistory(); - void redirectionTimerFired(Timer<FrameLoader>*); void checkCompletedTimerFired(Timer<FrameLoader>*); void checkLoadCompleteTimerFired(Timer<FrameLoader>*); @@ -479,7 +490,7 @@ namespace WebCore { void receivedFirstData(); void updatePolicyBaseURL(); - void setPolicyBaseURL(const KURL&); + void setPolicyBaseURL(const String&); // Also not cool. void stopLoadingSubframes(); diff --git a/WebCore/loader/FrameLoaderClient.h b/WebCore/loader/FrameLoaderClient.h index 35f02fc..d2d31ee 100644 --- a/WebCore/loader/FrameLoaderClient.h +++ b/WebCore/loader/FrameLoaderClient.h @@ -66,6 +66,10 @@ namespace WebCore { class ResourceRequest; +#ifdef ANDROID_HISTORY_CLIENT + class BackForwardList; +#endif + typedef void (FrameLoader::*FramePolicyFunction)(PolicyAction); class FrameLoaderClient { @@ -150,8 +154,14 @@ namespace WebCore { virtual void finishedLoading(DocumentLoader*) = 0; virtual void finalSetupForReplace(DocumentLoader*) = 0; - virtual void updateGlobalHistory(const KURL&) = 0; + virtual void updateGlobalHistoryForStandardLoad(const KURL&) = 0; + virtual void updateGlobalHistoryForReload(const KURL&) = 0; virtual bool shouldGoToHistoryItem(HistoryItem*) const = 0; +#ifdef ANDROID_HISTORY_CLIENT + virtual void dispatchDidAddHistoryItem(HistoryItem*) const = 0; + virtual void dispatchDidRemoveHistoryItem(HistoryItem*, int) const = 0; + virtual void dispatchDidChangeHistoryIndex(BackForwardList*) const = 0; +#endif virtual ResourceError cancelledError(const ResourceRequest&) = 0; virtual ResourceError blockedError(const ResourceRequest&) = 0; diff --git a/WebCore/loader/ImageDocument.cpp b/WebCore/loader/ImageDocument.cpp index 969405b..f622a52 100644 --- a/WebCore/loader/ImageDocument.cpp +++ b/WebCore/loader/ImageDocument.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,7 +35,6 @@ #include "FrameView.h" #include "HTMLImageElement.h" #include "HTMLNames.h" -#include "LocalizedStrings.h" #include "MouseEvent.h" #include "Page.h" #include "SegmentedString.h" @@ -43,6 +42,10 @@ #include "Text.h" #include "XMLTokenizer.h" +#if PLATFORM(MAC) +#include "ImageDocumentMac.h" +#endif + using std::min; namespace WebCore { @@ -117,11 +120,11 @@ void ImageTokenizer::finish() cachedImage->finish(); cachedImage->setResponse(m_doc->frame()->loader()->documentLoader()->response()); - - IntSize size = cachedImage->imageSize(); - if (size.width()) - m_doc->setTitle(imageTitle(cachedImage->response().suggestedFilename(), size)); - + + // FIXME: Need code to set the title for platforms other than Mac OS X. +#if PLATFORM(MAC) + finishImageLoad(m_doc, cachedImage); +#endif m_doc->imageChanged(); } @@ -167,7 +170,7 @@ void ImageDocument::createDocumentStructure() imageElement->setAttribute(styleAttr, "-webkit-user-select: none"); imageElement->setLoadManually(true); - imageElement->setSrc(url().string()); + imageElement->setSrc(url()); body->appendChild(imageElement, ec); diff --git a/WebCore/loader/MainResourceLoader.cpp b/WebCore/loader/MainResourceLoader.cpp index fa3d048..c591c2f 100644 --- a/WebCore/loader/MainResourceLoader.cpp +++ b/WebCore/loader/MainResourceLoader.cpp @@ -55,7 +55,7 @@ MainResourceLoader::~MainResourceLoader() PassRefPtr<MainResourceLoader> MainResourceLoader::create(Frame* frame) { - return adoptRef(new MainResourceLoader(frame)); + return new MainResourceLoader(frame); } void MainResourceLoader::receivedError(const ResourceError& error) diff --git a/WebCore/loader/NetscapePlugInStreamLoader.cpp b/WebCore/loader/NetscapePlugInStreamLoader.cpp index 86dbfcd..47c9599 100644 --- a/WebCore/loader/NetscapePlugInStreamLoader.cpp +++ b/WebCore/loader/NetscapePlugInStreamLoader.cpp @@ -46,7 +46,7 @@ NetscapePlugInStreamLoader::~NetscapePlugInStreamLoader() PassRefPtr<NetscapePlugInStreamLoader> NetscapePlugInStreamLoader::create(Frame* frame, NetscapePlugInStreamLoaderClient* client) { - return adoptRef(new NetscapePlugInStreamLoader(frame, client)); + return new NetscapePlugInStreamLoader(frame, client); } bool NetscapePlugInStreamLoader::isDone() const diff --git a/WebCore/loader/PluginDocument.cpp b/WebCore/loader/PluginDocument.cpp index ad14a4b..492c0f6 100644 --- a/WebCore/loader/PluginDocument.cpp +++ b/WebCore/loader/PluginDocument.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -88,7 +88,7 @@ void PluginTokenizer::createDocumentStructure() m_embedElement->setAttribute(heightAttr, "100%"); m_embedElement->setAttribute(nameAttr, "plugin"); - m_embedElement->setSrc(m_doc->url().string()); + m_embedElement->setSrc(m_doc->url()); m_embedElement->setType(m_doc->frame()->loader()->responseMIMEType()); body->appendChild(embedElement, ec); diff --git a/WebCore/loader/ResourceLoader.h b/WebCore/loader/ResourceLoader.h index 48d4f50..3f1784f 100644 --- a/WebCore/loader/ResourceLoader.h +++ b/WebCore/loader/ResourceLoader.h @@ -32,6 +32,7 @@ #include "ResourceHandleClient.h" #include "ResourceRequest.h" #include "ResourceResponse.h" +#include "ResourceLoader.h" #include <wtf/RefCounted.h> #include "AuthenticationChallenge.h" #include "KURL.h" diff --git a/WebCore/loader/SubresourceLoader.cpp b/WebCore/loader/SubresourceLoader.cpp index f840dd3..44f8548 100644 --- a/WebCore/loader/SubresourceLoader.cpp +++ b/WebCore/loader/SubresourceLoader.cpp @@ -118,7 +118,7 @@ PassRefPtr<SubresourceLoader> SubresourceLoader::create(Frame* frame, Subresourc fl->addExtraFieldsToRequest(newRequest, false, false); - RefPtr<SubresourceLoader> subloader(adoptRef(new SubresourceLoader(frame, client, sendResourceLoadCallbacks, shouldContentSniff))); + RefPtr<SubresourceLoader> subloader(new SubresourceLoader(frame, client, sendResourceLoadCallbacks, shouldContentSniff)); if (!subloader->load(newRequest)) return 0; diff --git a/WebCore/loader/TextResourceDecoder.cpp b/WebCore/loader/TextResourceDecoder.cpp index ef8a979..ef067f8 100644 --- a/WebCore/loader/TextResourceDecoder.cpp +++ b/WebCore/loader/TextResourceDecoder.cpp @@ -23,7 +23,9 @@ #include "config.h" #include "TextResourceDecoder.h" +#include "CString.h" #include "DOMImplementation.h" +#include "DeprecatedCString.h" #include "HTMLNames.h" #include "TextCodec.h" #include <wtf/ASCIICType.h> @@ -34,60 +36,6 @@ namespace WebCore { using namespace HTMLNames; -// You might think we should put these find functions elsewhere, perhaps with the -// similar functions that operate on UChar, but arguably only the decoder has -// a reason to process strings of char rather than UChar. - -static int find(const char* subject, size_t subjectLength, const char* target) -{ - size_t targetLength = strlen(target); - if (targetLength > subjectLength) - return -1; - for (size_t i = 0; i <= subjectLength - targetLength; ++i) { - bool match = true; - for (size_t j = 0; j < targetLength; ++j) { - if (subject[i + j] != target[j]) { - match = false; - break; - } - } - if (match) - return i; - } - return -1; -} - -static int findIgnoringCase(const char* subject, size_t subjectLength, const char* target) -{ - size_t targetLength = strlen(target); - if (targetLength > subjectLength) - return -1; -#ifndef NDEBUG - for (size_t i = 0; i < targetLength; ++i) - ASSERT(isASCIILower(target[i])); -#endif - for (size_t i = 0; i <= subjectLength - targetLength; ++i) { - bool match = true; - for (size_t j = 0; j < targetLength; ++j) { - if (toASCIILower(subject[i + j]) != target[j]) { - match = false; - break; - } - } - if (match) - return i; - } - return -1; -} - -static TextEncoding findTextEncoding(const char* encodingName, int length) -{ - Vector<char, 64> buffer(length + 1); - memcpy(buffer.data(), encodingName, length); - buffer[length] = '\0'; - return buffer.data(); -} - class KanjiCode { public: enum Type { ASCII, JIS, EUC, SJIS, UTF16, UTF8 }; @@ -320,8 +268,7 @@ const TextEncoding& TextResourceDecoder::defaultEncoding(ContentType contentType } TextResourceDecoder::TextResourceDecoder(const String& mimeType, const TextEncoding& specifiedDefaultEncoding) - : RefCounted<TextResourceDecoder>(0) - , m_contentType(determineContentType(mimeType)) + : m_contentType(determineContentType(mimeType)) , m_decoder(defaultEncoding(m_contentType, specifiedDefaultEncoding)) , m_source(DefaultEncoding) , m_checkedForBOM(false) @@ -349,29 +296,29 @@ void TextResourceDecoder::setEncoding(const TextEncoding& encoding, EncodingSour } // Returns the position of the encoding string. -static int findXMLEncoding(const char* str, int len, int& encodingLength) +static int findXMLEncoding(const DeprecatedCString &str, int &encodingLength) { - int pos = find(str, len, "encoding"); + int len = str.length(); + + int pos = str.find("encoding"); if (pos == -1) return -1; pos += 8; // Skip spaces and stray control characters. - while (pos < len && str[pos] <= ' ') + while (str[pos] <= ' ' && pos != len) ++pos; // Skip equals sign. - if (pos >= len || str[pos] != '=') + if (str[pos] != '=') return -1; ++pos; // Skip spaces and stray control characters. - while (pos < len && str[pos] <= ' ') + while (str[pos] <= ' ' && pos != len) ++pos; // Skip quotation mark. - if (pos >= len) - return - 1; char quoteMark = str[pos]; if (quoteMark != '"' && quoteMark != '\'') return -1; @@ -379,11 +326,12 @@ static int findXMLEncoding(const char* str, int len, int& encodingLength) // Find the trailing quotation mark. int end = pos; - while (end < len && str[end] != quoteMark) + while (str[end] != quoteMark) ++end; - if (end >= len) - return -1; + if (end == len) + return -1; + encodingLength = end - pos; return pos; } @@ -473,14 +421,14 @@ bool TextResourceDecoder::checkForCSSCharset(const char* data, size_t len, bool& if (pos == dataEnd) return false; - int encodingNameLength = pos - dataStart + 1; + CString encodingName(dataStart, pos - dataStart + 1); ++pos; if (!skipWhitespace(pos, dataEnd)) return false; if (*pos == ';') - setEncoding(findTextEncoding(dataStart, encodingNameLength), EncodingFromCSSCharset); + setEncoding(TextEncoding(encodingName.data()), EncodingFromCSSCharset); } } m_checkedForCSSCharset = true; @@ -548,11 +496,11 @@ bool TextResourceDecoder::checkForHeadCharset(const char* data, size_t len, bool ++xmlDeclarationEnd; if (xmlDeclarationEnd == pEnd) return false; - // No need for +1, because we have an extra "?" to lose at the end of XML declaration. - int len; - int pos = findXMLEncoding(ptr, xmlDeclarationEnd - ptr, len); + DeprecatedCString str(ptr, xmlDeclarationEnd - ptr); // No need for +1, because we have an extra "?" to lose at the end of XML declaration. + int len = 0; + int pos = findXMLEncoding(str, len); if (pos != -1) - setEncoding(findTextEncoding(ptr + pos, len), EncodingFromXMLHeader); + setEncoding(TextEncoding(str.mid(pos, len)), EncodingFromXMLHeader); // continue looking for a charset - it may be specified in an HTTP-Equiv meta } else if (ptr[0] == '<' && ptr[1] == 0 && ptr[2] == '?' && ptr[3] == 0 && ptr[4] == 'x' && ptr[5] == 0) { setEncoding(UTF16LittleEndianEncoding(), AutoDetectedEncoding); @@ -665,41 +613,40 @@ bool TextResourceDecoder::checkForHeadCharset(const char* data, size_t len, bool } if (!end && tag == metaTag && !sawNamespace) { - const char* str = tagContentStart; - int length = ptr - tagContentStart; + DeprecatedCString str(tagContentStart, ptr - tagContentStart); + str = str.lower(); int pos = 0; - while (pos < length) { - int charsetPos = findIgnoringCase(str + pos, length, "charset"); - if (charsetPos == -1) + while (pos < (int)str.length()) { + if ((pos = str.find("charset", pos, false)) == -1) break; - pos += charsetPos + 7; + pos += 7; // skip whitespace - while (pos < length && str[pos] <= ' ') + while (pos < (int)str.length() && str[pos] <= ' ') pos++; - if (pos == length) + if (pos == (int)str.length()) break; if (str[pos++] != '=') continue; - while (pos < length && + while (pos < (int)str.length() && (str[pos] <= ' ') || str[pos] == '=' || str[pos] == '"' || str[pos] == '\'') pos++; // end ? - if (pos == length) + if (pos == (int)str.length()) break; - int end = pos; - while (end < length && - str[end] != ' ' && str[end] != '"' && str[end] != '\'' && - str[end] != ';' && str[end] != '>') - end++; - setEncoding(findTextEncoding(str + pos, end - pos), EncodingFromMetaTag); + unsigned endpos = pos; + while (endpos < str.length() && + str[endpos] != ' ' && str[endpos] != '"' && str[endpos] != '\'' && + str[endpos] != ';' && str[endpos] != '>') + endpos++; + setEncoding(TextEncoding(str.mid(pos, endpos - pos)), EncodingFromMetaTag); if (m_source == EncodingFromMetaTag) return true; - if (end >= length || str[end] == '/' || str[end] == '>') + if (endpos >= str.length() || str[endpos] == '/' || str[endpos] == '>') break; - pos = end + 1; + pos = endpos + 1; } } else if (ptr - m_buffer.data() >= 512 && tag != scriptTag && tag != noscriptTag && tag != styleTag && tag != linkTag && tag != metaTag && tag != objectTag && diff --git a/WebCore/loader/android/DocumentLoaderAndroid.cpp b/WebCore/loader/android/DocumentLoaderAndroid.cpp new file mode 100644 index 0000000..f402495 --- /dev/null +++ b/WebCore/loader/android/DocumentLoaderAndroid.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2006 Zack Rusin <zack@kde.org> + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * + * 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 COMPUTER, 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 COMPUTER, 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 "DocumentLoader.h" + +#include "KURL.h" +#include <stdio.h> + +#define LOG_TAG "WebCore" +#undef LOG +#include <utils/Log.h> + +namespace WebCore { + +#if 0 // FIXME: no longer defined +bool DocumentLoader::getResponseModifiedHeader(String& modified) const +{ + LOGV("--- unimpl %s\n", __PRETTY_FUNCTION__); + return false; +} +#endif + +} + diff --git a/WebCore/loader/icon/IconDatabase.cpp b/WebCore/loader/icon/IconDatabase.cpp index a5dfb25..79250b8 100644 --- a/WebCore/loader/icon/IconDatabase.cpp +++ b/WebCore/loader/icon/IconDatabase.cpp @@ -37,7 +37,6 @@ #include "IntSize.h" #include "KURL.h" #include "Logging.h" -#include "MainThread.h" #include "PageURLRecord.h" #include "SQLiteStatement.h" #include "SQLiteTransaction.h" @@ -102,7 +101,7 @@ static IconDatabaseClient* defaultClient() IconDatabase* iconDatabase() { if (!sharedIconDatabase) { - initializeThreadingAndMainThread(); + initializeThreading(); sharedIconDatabase = new IconDatabase; } return sharedIconDatabase; @@ -154,6 +153,11 @@ bool IconDatabase::open(const String& databasePath) void IconDatabase::close() { +#ifdef ANDROID + // Since we close and reopen the database within the same process, reset + // this flag + m_initialPruningComplete = false; +#endif ASSERT_NOT_SYNC_THREAD(); if (m_syncThreadRunning) { @@ -219,11 +223,13 @@ void IconDatabase::removeAllIcons() Image* IconDatabase::iconForPageURL(const String& pageURLOriginal, const IntSize& size, bool cache) { ASSERT_NOT_SYNC_THREAD(); + + ASSERT(!pageURLOriginal.isNull()); - // pageURLOriginal cannot be stored without being deep copied first. + // pageURLOriginal can not be stored without being deep copied first. // We should go our of our way to only copy it if we have to store it - if (!isOpen() || pageURLOriginal.isEmpty()) + if (!isOpen()) return defaultIcon(size); MutexLocker locker(m_urlAndIconLock); diff --git a/WebCore/loader/icon/IconDatabase.h b/WebCore/loader/icon/IconDatabase.h index bdd2455..ea48c16 100644 --- a/WebCore/loader/icon/IconDatabase.h +++ b/WebCore/loader/icon/IconDatabase.h @@ -32,13 +32,13 @@ #endif #include "StringHash.h" +#if ENABLE(ICONDATABASE) +#include "Threading.h" +#endif #include "Timer.h" #include <wtf/HashSet.h> #include <wtf/Noncopyable.h> #include <wtf/OwnPtr.h> -#if ENABLE(ICONDATABASE) -#include <wtf/Threading.h> -#endif namespace WebCore { diff --git a/WebCore/loader/icon/IconLoader.h b/WebCore/loader/icon/IconLoader.h index a7194d8..aba70b4 100644 --- a/WebCore/loader/icon/IconLoader.h +++ b/WebCore/loader/icon/IconLoader.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,16 +26,15 @@ #ifndef IconLoader_h #define IconLoader_h +#include "KURL.h" #include "SubresourceLoaderClient.h" #include <memory> -#include <wtf/Forward.h> #include <wtf/Noncopyable.h> -#include <wtf/RefPtr.h> +#include <wtf/PassRefPtr.h> namespace WebCore { class Frame; -class KURL; class SharedBuffer; class IconLoader : private SubresourceLoaderClient, Noncopyable { diff --git a/WebCore/loader/icon/IconRecord.cpp b/WebCore/loader/icon/IconRecord.cpp index 52259ed..8b3d5f9 100644 --- a/WebCore/loader/icon/IconRecord.cpp +++ b/WebCore/loader/icon/IconRecord.cpp @@ -41,8 +41,7 @@ namespace WebCore { IconRecord::IconRecord(const String& url) - : RefCounted<IconRecord>(0) - , m_iconURL(url) + : m_iconURL(url) , m_stamp(0) , m_dataSet(false) { diff --git a/WebCore/loader/loader.cpp b/WebCore/loader/loader.cpp index 39e6c07..0c7545f 100644 --- a/WebCore/loader/loader.cpp +++ b/WebCore/loader/loader.cpp @@ -3,7 +3,7 @@ Copyright (C) 2001 Dirk Mueller (mueller@kde.org) Copyright (C) 2002 Waldo Bastian (bastian@kde.org) Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) - Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + Copyright (C) 2004, 2005, 2006, 2007 Apple 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 @@ -66,23 +66,42 @@ void Loader::servePendingRequests() // get the first pending request Request* req = m_requestsPending.take(0); DocLoader* dl = req->docLoader(); +#ifndef ANDROID_PRELOAD_CHANGES dl->decrementRequestCount(); +#endif ResourceRequest request(req->cachedResource()->url()); +#ifdef ANDROID + request.setCachedResource(req->cachedResource()); +#endif if (!req->cachedResource()->accept().isEmpty()) request.setHTTPAccept(req->cachedResource()->accept()); KURL r = dl->doc()->url(); - if ((r.protocolIs("http") || r.protocolIs("https")) && r.path().isEmpty()) + if (r.protocol().startsWith("http") && r.path().isEmpty()) r.setPath("/"); request.setHTTPReferrer(r.string()); - + DeprecatedString domain = r.host(); + if (dl->doc()->isHTMLDocument()) + domain = static_cast<HTMLDocument*>(dl->doc())->domain().deprecatedString(); + RefPtr<SubresourceLoader> loader = SubresourceLoader::create(dl->doc()->frame(), this, request, req->shouldSkipCanLoadCheck(), req->sendResourceLoadCallbacks()); if (loader) { m_requestsLoading.add(loader.release(), req); +#ifdef ANDROID_PRELOAD_CHANGES + req->cachedResource()->setRequestedFromNetworkingLayer(); + } else { + dl->decrementRequestCount(); + dl->setLoadInProgress(true); + req->cachedResource()->error(); + dl->setLoadInProgress(false); + + delete req; + } +#else dl->incrementRequestCount(); break; } @@ -92,6 +111,7 @@ void Loader::servePendingRequests() dl->setLoadInProgress(false); delete req; +#endif } } @@ -109,16 +129,16 @@ void Loader::didFinishLoading(SubresourceLoader* loader) CachedResource* object = req->cachedResource(); - // If we got a 4xx response, we're pretending to have received a network - // error, so we can't send the successful data() and finish() callbacks. - if (!object->errorOccurred()) { - docLoader->setLoadInProgress(true); - object->data(loader->resourceData(), true); - docLoader->setLoadInProgress(false); - object->finish(); - } + docLoader->setLoadInProgress(true); + object->data(loader->resourceData(), true); + docLoader->setLoadInProgress(false); + object->finish(); delete req; + +#ifdef ANDROID_PRELOAD_CHANGES + docLoader->checkForPendingPreloads(); +#endif servePendingRequests(); } @@ -148,9 +168,16 @@ void Loader::didFail(SubresourceLoader* loader, bool cancelled) } docLoader->setLoadInProgress(false); +#ifdef ANDROID_PRELOAD_CHANGES + if (cancelled || !object->isPreloaded()) +#endif cache()->remove(object); delete req; + +#ifdef ANDROID_PRELOAD_CHANGES + docLoader->checkForPendingPreloads(); +#endif servePendingRequests(); } @@ -198,14 +225,6 @@ void Loader::didReceiveData(SubresourceLoader* loader, const char* data, int siz return; CachedResource* object = request->cachedResource(); - if (object->errorOccurred()) - return; - - if (object->response().httpStatusCode() / 100 == 4) { - // Treat a 4xx response like a network error. - object->error(); - return; - } // Set the data. if (request->isMultipart()) { diff --git a/WebCore/loader/mac/ImageDocumentMac.h b/WebCore/loader/mac/ImageDocumentMac.h new file mode 100644 index 0000000..3c7c509 --- /dev/null +++ b/WebCore/loader/mac/ImageDocumentMac.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, 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 COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * 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. + */ + +#ifndef ImageDocumentMac_h +#define ImageDocumentMac_h + +namespace WebCore { + + class CachedImage; + class Document; + + void finishImageLoad(Document*, CachedImage*); + +} + +#endif diff --git a/WebCore/loader/mac/ImageDocumentMac.mm b/WebCore/loader/mac/ImageDocumentMac.mm new file mode 100644 index 0000000..755f448 --- /dev/null +++ b/WebCore/loader/mac/ImageDocumentMac.mm @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, 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 COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * 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. + */ + +#import "config.h" +#import "ImageDocumentMac.h" + +#include "CachedImage.h" +#include "Document.h" +#include "FrameLoader.h" +#include "Frame.h" +#include "WebCoreFrameBridge.h" +#include "DocumentLoader.h" + +namespace WebCore { + +void finishImageLoad(Document* document, CachedImage* image) +{ + Frame* frame = document->frame(); + const ResourceResponse& response = frame->loader()->documentLoader()->response(); + + IntSize size = image->imageSize(); + if (size.width()) + document->setTitle([frame->bridge() imageTitleForFilename:response.suggestedFilename() size:size]); +} + +} diff --git a/WebCore/loader/mac/LoaderNSURLExtras.h b/WebCore/loader/mac/LoaderNSURLExtras.h index ce5a490..39ef222 100644 --- a/WebCore/loader/mac/LoaderNSURLExtras.h +++ b/WebCore/loader/mac/LoaderNSURLExtras.h @@ -32,6 +32,17 @@ extern "C" { #endif +NSURL *urlByRemovingComponent(NSURL *url, CFURLComponentType component); +NSURL *urlByRemovingFragment(NSURL *url); +NSString *urlOriginalDataAsString(NSURL *url); +NSData *urlOriginalData(NSURL *url); +NSURL *urlWithData(NSData *data); +NSURL *urlWithDataRelativeToURL(NSData *data, NSURL *baseURL); +NSURL *urlByRemovingResourceSpecifier(NSURL *url); +BOOL urlIsFileURL(NSURL *url); +BOOL stringIsFileURL(NSString *urlString); +BOOL urlIsEmpty(NSURL *url); +NSURL *canonicalURL(NSURL *url); NSString *suggestedFilenameWithMIMEType(NSURL *url, NSString *MIMEType); #ifdef __cplusplus diff --git a/WebCore/loader/mac/LoaderNSURLExtras.m b/WebCore/loader/mac/LoaderNSURLExtras.m index 9a507f5..76ad5c7 100644 --- a/WebCore/loader/mac/LoaderNSURLExtras.m +++ b/WebCore/loader/mac/LoaderNSURLExtras.m @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) * * Redistribution and use in source and binary forms, with or without @@ -37,10 +37,166 @@ #import "MIMETypeRegistry.h" #import "PlatformString.h" #import "WebCoreNSStringExtras.h" +#import "WebCoreSystemInterface.h" using namespace WebCore; -static bool vectorContainsString(const Vector<String>& vector, const String& string) +NSURL *urlByRemovingComponent(NSURL *url, CFURLComponentType component) +{ + if (!url) + return nil; + + CFRange fragRg = CFURLGetByteRangeForComponent((CFURLRef)url, component, NULL); + // Check to see if a fragment exists before decomposing the URL. + if (fragRg.location == kCFNotFound) + return url; + + UInt8 *urlBytes, buffer[2048]; + CFIndex numBytes = CFURLGetBytes((CFURLRef)url, buffer, 2048); + if (numBytes == -1) { + numBytes = CFURLGetBytes((CFURLRef)url, NULL, 0); + urlBytes = static_cast<UInt8*>(malloc(numBytes)); + CFURLGetBytes((CFURLRef)url, urlBytes, numBytes); + } else + urlBytes = buffer; + + NSURL *result = (NSURL *)CFMakeCollectable(CFURLCreateWithBytes(NULL, urlBytes, fragRg.location - 1, kCFStringEncodingUTF8, NULL)); + if (!result) + result = (NSURL *)CFMakeCollectable(CFURLCreateWithBytes(NULL, urlBytes, fragRg.location - 1, kCFStringEncodingISOLatin1, NULL)); + + if (urlBytes != buffer) free(urlBytes); + return result ? [result autorelease] : url; +} + +NSURL *urlByRemovingFragment(NSURL *url) +{ + return urlByRemovingComponent(url, kCFURLComponentFragment); +} + +NSString *urlOriginalDataAsString(NSURL *url) +{ + return [[[NSString alloc] initWithData:urlOriginalData(url) encoding:NSISOLatin1StringEncoding] autorelease]; +} + +#define URL_BYTES_BUFFER_LENGTH 2048 + +NSData *urlOriginalData(NSURL *url) +{ + if (!url) + return nil; + + UInt8 *buffer = (UInt8 *)malloc(URL_BYTES_BUFFER_LENGTH); + CFIndex bytesFilled = CFURLGetBytes((CFURLRef)url, buffer, URL_BYTES_BUFFER_LENGTH); + if (bytesFilled == -1) { + CFIndex bytesToAllocate = CFURLGetBytes((CFURLRef)url, NULL, 0); + buffer = (UInt8 *)realloc(buffer, bytesToAllocate); + bytesFilled = CFURLGetBytes((CFURLRef)url, buffer, bytesToAllocate); + ASSERT(bytesFilled == bytesToAllocate); + } + + // buffer is adopted by the NSData + NSData *data = [NSData dataWithBytesNoCopy:buffer length:bytesFilled freeWhenDone:YES]; + + NSURL *baseURL = (NSURL *)CFURLGetBaseURL((CFURLRef)url); + if (baseURL) + return urlOriginalData(urlWithDataRelativeToURL(data, baseURL)); + return data; +} + +NSURL *urlWithData(NSData *data) +{ + if (data == nil) + return nil; + + return urlWithDataRelativeToURL(data, nil); +} + +static inline id WebCFAutorelease(CFTypeRef obj) +{ + if (obj) + CFMakeCollectable(obj); + [(id)obj autorelease]; + return (id)obj; +} + +NSURL *urlWithDataRelativeToURL(NSData *data, NSURL *baseURL) +{ + if (data == nil) + return nil; + + NSURL *result = nil; + size_t length = [data length]; + if (length > 0) { + // work around <rdar://4470771>: CFURLCreateAbsoluteURLWithBytes(.., TRUE) doesn't remove non-path components. + baseURL = urlByRemovingResourceSpecifier(baseURL); + + const UInt8 *bytes = static_cast<const UInt8*>([data bytes]); + // NOTE: We use UTF-8 here since this encoding is used when computing strings when returning URL components + // (e.g calls to NSURL -path). However, this function is not tolerant of illegal UTF-8 sequences, which + // could either be a malformed string or bytes in a different encoding, like shift-jis, so we fall back + // onto using ISO Latin 1 in those cases. + result = WebCFAutorelease(CFURLCreateAbsoluteURLWithBytes(NULL, bytes, length, kCFStringEncodingUTF8, (CFURLRef)baseURL, YES)); + if (!result) + result = WebCFAutorelease(CFURLCreateAbsoluteURLWithBytes(NULL, bytes, length, kCFStringEncodingISOLatin1, (CFURLRef)baseURL, YES)); + } else + result = [NSURL URLWithString:@""]; + + return result; +} + +NSURL *urlByRemovingResourceSpecifier(NSURL *url) +{ + return urlByRemovingComponent(url, kCFURLComponentResourceSpecifier); +} + + +BOOL urlIsFileURL(NSURL *url) +{ + if (!url) + return false; + + return stringIsFileURL(urlOriginalDataAsString(url)); +} + +BOOL stringIsFileURL(NSString *urlString) +{ + return [urlString rangeOfString:@"file:" options:(NSCaseInsensitiveSearch | NSAnchoredSearch)].location != NSNotFound; +} + +BOOL urlIsEmpty(NSURL *url) +{ + if (!url) + return false; + if (!CFURLGetBaseURL((CFURLRef)url)) + return CFURLGetBytes((CFURLRef)url, NULL, 0) == 0; + return [urlOriginalData(url) length] == 0; +} + +NSURL *canonicalURL(NSURL *url) +{ + if (!url) + return nil; + + NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url]; + Class concreteClass = wkNSURLProtocolClassForReqest(request); + if (!concreteClass) { + [request release]; + return url; + } + + // This applies NSURL's concept of canonicalization, but not KURL's concept. It would + // make sense to apply both, but when we tried that it caused a performance degradation + // (see 5315926). It might make sense to apply only the KURL concept and not the NSURL + // concept, but it's too risky to make that change for WebKit 3.0. + NSURLRequest *newRequest = [concreteClass canonicalRequestForRequest:request]; + NSURL *newURL = [newRequest URL]; + NSURL *result = [[newURL retain] autorelease]; + [request release]; + + return result; +} + +static bool vectorContainsString(Vector<String> vector, String string) { int size = vector.size(); for (int i = 0; i < size; i++) @@ -58,7 +214,7 @@ NSString *suggestedFilenameWithMIMEType(NSURL *url, NSString *MIMEType) if ([filename length] == 0 || [lastPathComponent isEqualToString:@"/"]) { // lastPathComponent is no good, try the host. - NSString *host = KURL(url).host(); + NSString *host = (NSString *)(KURL(url).host()); filename = filenameByFixingIllegalCharacters(host); if ([filename length] == 0) { // Can't make a filename using this URL, use "unknown". diff --git a/WebCore/loader/mac/UserStyleSheetLoader.cpp b/WebCore/loader/mac/UserStyleSheetLoader.cpp index d5d037d..349a994 100644 --- a/WebCore/loader/mac/UserStyleSheetLoader.cpp +++ b/WebCore/loader/mac/UserStyleSheetLoader.cpp @@ -54,9 +54,9 @@ UserStyleSheetLoader::~UserStyleSheetLoader() } } -void UserStyleSheetLoader::setCSSStyleSheet(const String& /*URL*/, const String& /*charset*/, const CachedCSSStyleSheet* sheet) +void UserStyleSheetLoader::setCSSStyleSheet(const String& /*URL*/, const String& /*charset*/, const String& sheet) { m_document->removePendingSheet(); if (Frame* frame = m_document->frame()) - frame->setUserStyleSheet(sheet->sheetText()); + frame->setUserStyleSheet(sheet); } diff --git a/WebCore/loader/mac/UserStyleSheetLoader.h b/WebCore/loader/mac/UserStyleSheetLoader.h index e2276c0..9159273 100644 --- a/WebCore/loader/mac/UserStyleSheetLoader.h +++ b/WebCore/loader/mac/UserStyleSheetLoader.h @@ -45,7 +45,7 @@ namespace WebCore { ~UserStyleSheetLoader(); private: - virtual void setCSSStyleSheet(const String& URL, const String& charset, const CachedCSSStyleSheet* sheet); + virtual void setCSSStyleSheet(const String& URL, const String& charset, const String& sheet); RefPtr<Document> m_document; CachedCSSStyleSheet* m_cachedSheet; |