[iOS] Upstream WebCore/loader changes
authordbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 19 Dec 2013 18:10:07 +0000 (18:10 +0000)
committerdbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 19 Dec 2013 18:10:07 +0000 (18:10 +0000)
https://bugs.webkit.org/show_bug.cgi?id=125879

Reviewed by Darin Adler.

* WebCore.exp.in: Added symbols for MemoryCache::{addImageToCache, removeImageFromCache}().
* loader/DocumentLoader.cpp:
(WebCore::areAllLoadersPageCacheAcceptable): Added.
(WebCore::DocumentLoader::DocumentLoader): Initialize m_subresourceLoadersArePageCacheAcceptable.
(WebCore::DocumentLoader::stopLoading): Modified to conditionally call areAllLoadersPageCacheAcceptable().
(WebCore::DocumentLoader::handleSubstituteDataLoadSoon): Modified to query FrameLoader::loadsSynchronously()
whether to load substitute data immediately or to schedule a load.
(WebCore::DocumentLoader::responseReceived): Modified to create a content filer when the response protocol
is either HTTP or HTTPS, assuming content filtering is enabled.
(WebCore::DocumentLoader::dataReceived): Modified to call DocumentLoader::setContentFilterForBlockedLoad()
as appropriate.
(WebCore::DocumentLoader::clearMainResourceLoader): Added PLATFORM(IOS)-guarded code. Also added a
FIXME comment to remove the PLATFORM(IOS)-guard once we upstream the iOS changes to ResourceRequest.h.
(WebCore::DocumentLoader::setResponseMIMEType): Added; guard by PLATFORM(IOS). Also added FIXME comment.
(WebCore::DocumentLoader::startLoadingMainResource): Added PLATFORM(IOS)-guarded code. Also added a
FIXME comment to remove the PLATFORM(IOS)-guard once we upstream the iOS changes to ResourceRequest.h.
I also substituted static NeverDestroyed<> for DEFINE_STATIC_LOCAL.
(WebCore::DocumentLoader::setContentFilterForBlockedLoad): Added; guarded by USE(CONTENT_FILTERING).
(WebCore::DocumentLoader::handleContentFilterRequest): Added; guarded by USE(CONTENT_FILTERING) and PLATFORM(IOS).
Also added a FIXME comment to remove the PLATFORM(IOS) guard inside its function body once we upstream
file ContentFilterIOS.mm and implement ContentFilter::requestUnblockAndDispatchIfSuccessful() for Mac.
* loader/DocumentLoader.h:
(WebCore::DocumentLoader::setResponse): Added; guard by PLATFORM(IOS). Also added a FIXME comment as
this method seems to violate the encapsulation of DocumentLoader.
(WebCore::DocumentLoader::subresourceLoadersArePageCacheAcceptable): Added.
(WebCore::DocumentLoader::documentURL): Added; returns the URL of the document resulting from the DocumentLoader.
* loader/DocumentWriter.cpp:
(WebCore::DocumentWriter::createDocument): Added iOS-specific code to create a PDF document.
* loader/EmptyClients.cpp:
(WebCore::EmptyChromeClient::openDateTimeChooser): Opt out of compiling this code for iOS. Also substituted
nullptr for 0.
* loader/EmptyClients.h:
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::FrameProgressTracker::~FrameProgressTracker):
(WebCore::FrameLoader::FrameLoader): Initialize m_loadsSynchronously.
(WebCore::FrameLoader::initForSynthesizedDocument): Added; guarded by PLATFORM(IOS). Also added FIXME comment.
(WebCore::FrameLoader::checkCompleted): Added iOS-specific code with FIXME comment.
(WebCore::FrameLoader::willLoadMediaElementURL): Added iOS-specific code.
(WebCore::FrameLoader::stopForUserCancel): Added iOS-specific code and FIXME comment.
(WebCore::FrameLoader::commitProvisionalLoad): Added iOS-specific code and FIXME comment.
(WebCore::FrameLoader::transitionToCommitted): Opt out of ENABLE(TOUCH_EVENTS) logic when building for iOS.
(WebCore::FrameLoader::didFirstLayout): Added iOS-specific code.
(WebCore::FrameLoader::connectionProperties): Added; guarded by PLATFORM(IOS).
(WebCore::createWindow): Added iOS-specific code and FIXME comment.
* loader/FrameLoader.h:
(WebCore::FrameLoader::setLoadsSynchronously): Added.
(WebCore::FrameLoader::loadsSynchronously): Added.
* loader/FrameLoaderClient.h:
* loader/HistoryController.cpp:
(WebCore::HistoryController::restoreScrollPositionAndViewState): Opt out of scroll position logic when building for iOS.
(WebCore::HistoryController::replaceCurrentItem): Added.
* loader/HistoryController.h:
* loader/PlaceholderDocument.h: Changed access control of constructor from private to protected and removed the FINAL
keyword from the class so that we can subclass PlaceholderDocument on iOS.
* loader/PolicyChecker.cpp:
(WebCore::PolicyChecker::checkNavigationPolicy): Added USE(QUICK_LOOK)- and USE(CONTENT_FILTERING)-guarded code.
* loader/ResourceBuffer.cpp:
(WebCore::ResourceBuffer::shouldUsePurgeableMemory): Added; guarded by PLATFORM(IOS).
* loader/ResourceBuffer.h:
* loader/ResourceLoadNotifier.cpp:
(WebCore::ResourceLoadNotifier::dispatchWillSendRequest): Added USE(QUICK_LOOK)-guarded code.
* loader/ResourceLoadScheduler.cpp:
(WebCore::ResourceLoadScheduler::scheduleSubresourceLoad): Added iOS-specific code.
(WebCore::ResourceLoadScheduler::scheduleLoad): Ditto.
(WebCore::ResourceLoadScheduler::remove): Added iOS-specific code with FIXME comment.
(WebCore::ResourceLoadScheduler::crossOriginRedirectReceived): Added null-check for variable oldHost. Also added
iOS-specific code.
(WebCore::ResourceLoadScheduler::servePendingRequests): Added iOS-specific code.
* loader/ResourceLoader.cpp:
(WebCore::ResourceLoader::init): Ditto.
(WebCore::ResourceLoader::willSendRequest): Ditto.
(WebCore::ResourceLoader::connectionProperties): Added; guarded by PLATFORM(IOS).
* loader/ResourceLoader.h:
(WebCore::ResourceLoader::startLoading): Added; guarded by PLATFORM(IOS).
(WebCore::ResourceLoader::iOSOriginalRequest): Added; iOS-specific.
* loader/SubframeLoader.cpp:
(WebCore::SubframeLoader::loadPlugin): Added iOS-specific code.
* loader/SubresourceLoader.cpp:
(WebCore::SubresourceLoader::create): Ditto.
(WebCore::SubresourceLoader::startLoading): Added; guarded by PLATFORM(IOS).
(WebCore::SubresourceLoader::didFinishLoading): Added iOS-specific code.
(WebCore::SubresourceLoader::willCancel): Ditto.
(WebCore::SubresourceLoader::notifyDone): Ditto.
(WebCore::SubresourceLoader::releaseResources): Ditto.
* loader/SubresourceLoader.h:
* loader/appcache/ApplicationCacheStorage.cpp:
(WebCore::ApplicationCacheStorage::loadCacheGroup): Added iOS-specific code.
(WebCore::ApplicationCacheStorage::loadManifestHostHashes): Ditto.
(WebCore::ApplicationCacheStorage::cacheGroupForURL): Ditto.
(WebCore::ApplicationCacheStorage::fallbackCacheGroupForURL): Ditto.
(WebCore::ApplicationCacheStorage::calculateQuotaForOrigin): Ditto.
(WebCore::ApplicationCacheStorage::calculateUsageForOrigin): Ditto.
(WebCore::ApplicationCacheStorage::calculateRemainingSizeForOriginExcludingCache): Ditto.
(WebCore::ApplicationCacheStorage::storeUpdatedQuotaForOrigin): Ditto.
(WebCore::ApplicationCacheStorage::executeSQLCommand): Ditto.
(WebCore::ApplicationCacheStorage::verifySchemaVersion): Ditto.
(WebCore::ApplicationCacheStorage::openDatabase): Ditto.
(WebCore::ApplicationCacheStorage::executeStatement): Ditto.
(WebCore::ApplicationCacheStorage::store): Ditto.
(WebCore::ApplicationCacheStorage::storeUpdatedType): Ditto.
(WebCore::ApplicationCacheStorage::ensureOriginRecord): Ditto.
(WebCore::ApplicationCacheStorage::loadCache): Ditto.
(WebCore::ApplicationCacheStorage::remove): Ditto.
(WebCore::ApplicationCacheStorage::empty): Ditto.
(WebCore::ApplicationCacheStorage::storeCopyOfCache): Ditto.
(WebCore::ApplicationCacheStorage::manifestURLs): Ditto.
(WebCore::ApplicationCacheStorage::cacheGroupSize): Ditto.
(WebCore::ApplicationCacheStorage::deleteCacheGroup): Ditto.
(WebCore::ApplicationCacheStorage::vacuumDatabaseFile): Ditto.
* loader/cache/CachedImage.cpp:
(WebCore::CachedImage::CachedImage): Added.
(WebCore::CachedImage::imageSizeForRenderer): Added iOS-specific code.
(WebCore::CachedImageManual::CachedImageManual): Added; guarded by USE(CF). Also added FIXME comment to incorporate
the functionality of this class into CachedImage and to remove the USE(CF)-guard once we make MemoryCache::addImageToCache()
platform-independent.
(WebCore::CachedImageManual::mustRevalidateDueToCacheHeaders): Added; guarded by USE(CF).
* loader/cache/CachedImage.h: Removed FINAL keyword from class so that we can define derived class CachedImageManual.
(WebCore::CachedImage::isManual): Added; guarded by USE(CF). Also added FIXME comment.
(WebCore::CachedImageManual::addFakeClient): Added; guarded by USE(CF).
(WebCore::CachedImageManual::removeFakeClient): Added; guarded by USE(CF).
* loader/cache/CachedResource.cpp:
(WebCore::CachedResource::load): Added iOS-specific code.
* loader/cache/CachedResource.h:
* loader/cache/CachedResourceLoader.cpp:
(WebCore::CachedResourceLoader::loadDone): Added argument shouldPerformPostLoadActions, defaults to true. Modified
to conditionally call performPostLoadActions() with respect to the argument shouldPerformPostLoadActions.
(WebCore::CachedResourceLoader::preload): Added iOS-specific code.
(WebCore::CachedResourceLoader::checkForPendingPreloads): Ditto.
* loader/cache/CachedResourceLoader.h:
* loader/cache/MemoryCache.cpp:
(WebCore::memoryCache):
(WebCore::MemoryCache::add): Added iOS-specific code.
(WebCore::MemoryCache::revalidationFailed): Ditto.
(WebCore::MemoryCache::resourceForRequest): Ditto.
(WebCore::MemoryCache::addImageToCache): Added; guarded by USE(CF). Also added FIXME comment.
(WebCore::MemoryCache::removeImageFromCache): Added; guarded by USE(CF). Also added FIXME comment.
(WebCore::MemoryCache::pruneLiveResources): Modified to take argument shouldDestroyDecodedDataForAllLiveResources.
(WebCore::MemoryCache::pruneLiveResourcesToSize): Modified to take argument shouldDestroyDecodedDataForAllLiveResources,
defaults to false. When this argument is true we destroy the decoded data for all live resources from the memory cache.
Such functionality is useful when the system is running low on memory.
(WebCore::MemoryCache::evict): Added iOS-specific code.
* loader/cache/MemoryCache.h:
* loader/cf/SubresourceLoaderCF.cpp:
(WebCore::SubresourceLoader::didReceiveDataArray): Actually make this code compile. In particular, there is no
method called sendDataToResource on SubresourceLoader or in its class hierarchy.
* loader/mac/DocumentLoaderMac.cpp:
(WebCore::DocumentLoader::schedule): This method has an empty implementation when building for iOS.
(WebCore::DocumentLoader::unschedule): Ditto.
* platform/graphics/BitmapImage.h: Exposed decodedSize() to access the decoded size of the bitmap image.
This functionality is used in MemoryCache::addImageToCache().

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

35 files changed:
Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebCore/loader/DocumentLoader.cpp
Source/WebCore/loader/DocumentLoader.h
Source/WebCore/loader/DocumentWriter.cpp
Source/WebCore/loader/EmptyClients.cpp
Source/WebCore/loader/EmptyClients.h
Source/WebCore/loader/FrameLoader.cpp
Source/WebCore/loader/FrameLoader.h
Source/WebCore/loader/FrameLoaderClient.h
Source/WebCore/loader/HistoryController.cpp
Source/WebCore/loader/HistoryController.h
Source/WebCore/loader/PlaceholderDocument.h
Source/WebCore/loader/PolicyChecker.cpp
Source/WebCore/loader/ResourceBuffer.cpp
Source/WebCore/loader/ResourceBuffer.h
Source/WebCore/loader/ResourceLoadNotifier.cpp
Source/WebCore/loader/ResourceLoadScheduler.cpp
Source/WebCore/loader/ResourceLoader.cpp
Source/WebCore/loader/ResourceLoader.h
Source/WebCore/loader/SubframeLoader.cpp
Source/WebCore/loader/SubresourceLoader.cpp
Source/WebCore/loader/SubresourceLoader.h
Source/WebCore/loader/appcache/ApplicationCacheStorage.cpp
Source/WebCore/loader/cache/CachedImage.cpp
Source/WebCore/loader/cache/CachedImage.h
Source/WebCore/loader/cache/CachedResource.cpp
Source/WebCore/loader/cache/CachedResource.h
Source/WebCore/loader/cache/CachedResourceLoader.cpp
Source/WebCore/loader/cache/CachedResourceLoader.h
Source/WebCore/loader/cache/MemoryCache.cpp
Source/WebCore/loader/cache/MemoryCache.h
Source/WebCore/loader/cf/SubresourceLoaderCF.cpp
Source/WebCore/loader/mac/DocumentLoaderMac.cpp
Source/WebCore/platform/graphics/BitmapImage.h

index 414aa4a..3bb058f 100644 (file)
@@ -1,3 +1,161 @@
+2013-12-19  Daniel Bates  <dabates@apple.com>
+
+        [iOS] Upstream WebCore/loader changes
+        https://bugs.webkit.org/show_bug.cgi?id=125879
+
+        Reviewed by Darin Adler.
+
+        * WebCore.exp.in: Added symbols for MemoryCache::{addImageToCache, removeImageFromCache}().
+        * loader/DocumentLoader.cpp:
+        (WebCore::areAllLoadersPageCacheAcceptable): Added.
+        (WebCore::DocumentLoader::DocumentLoader): Initialize m_subresourceLoadersArePageCacheAcceptable.
+        (WebCore::DocumentLoader::stopLoading): Modified to conditionally call areAllLoadersPageCacheAcceptable().
+        (WebCore::DocumentLoader::handleSubstituteDataLoadSoon): Modified to query FrameLoader::loadsSynchronously()
+        whether to load substitute data immediately or to schedule a load.
+        (WebCore::DocumentLoader::responseReceived): Modified to create a content filer when the response protocol
+        is either HTTP or HTTPS, assuming content filtering is enabled.
+        (WebCore::DocumentLoader::dataReceived): Modified to call DocumentLoader::setContentFilterForBlockedLoad()
+        as appropriate.
+        (WebCore::DocumentLoader::clearMainResourceLoader): Added PLATFORM(IOS)-guarded code. Also added a
+        FIXME comment to remove the PLATFORM(IOS)-guard once we upstream the iOS changes to ResourceRequest.h.
+        (WebCore::DocumentLoader::setResponseMIMEType): Added; guard by PLATFORM(IOS). Also added FIXME comment.
+        (WebCore::DocumentLoader::startLoadingMainResource): Added PLATFORM(IOS)-guarded code. Also added a
+        FIXME comment to remove the PLATFORM(IOS)-guard once we upstream the iOS changes to ResourceRequest.h.
+        I also substituted static NeverDestroyed<> for DEFINE_STATIC_LOCAL.
+        (WebCore::DocumentLoader::setContentFilterForBlockedLoad): Added; guarded by USE(CONTENT_FILTERING).
+        (WebCore::DocumentLoader::handleContentFilterRequest): Added; guarded by USE(CONTENT_FILTERING) and PLATFORM(IOS).
+        Also added a FIXME comment to remove the PLATFORM(IOS) guard inside its function body once we upstream
+        file ContentFilterIOS.mm and implement ContentFilter::requestUnblockAndDispatchIfSuccessful() for Mac.
+        * loader/DocumentLoader.h:
+        (WebCore::DocumentLoader::setResponse): Added; guard by PLATFORM(IOS). Also added a FIXME comment as
+        this method seems to violate the encapsulation of DocumentLoader.
+        (WebCore::DocumentLoader::subresourceLoadersArePageCacheAcceptable): Added.
+        (WebCore::DocumentLoader::documentURL): Added; returns the URL of the document resulting from the DocumentLoader.
+        * loader/DocumentWriter.cpp:
+        (WebCore::DocumentWriter::createDocument): Added iOS-specific code to create a PDF document.
+        * loader/EmptyClients.cpp:
+        (WebCore::EmptyChromeClient::openDateTimeChooser): Opt out of compiling this code for iOS. Also substituted
+        nullptr for 0.
+        * loader/EmptyClients.h:
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::FrameProgressTracker::~FrameProgressTracker):
+        (WebCore::FrameLoader::FrameLoader): Initialize m_loadsSynchronously.
+        (WebCore::FrameLoader::initForSynthesizedDocument): Added; guarded by PLATFORM(IOS). Also added FIXME comment.
+        (WebCore::FrameLoader::checkCompleted): Added iOS-specific code with FIXME comment.
+        (WebCore::FrameLoader::willLoadMediaElementURL): Added iOS-specific code.
+        (WebCore::FrameLoader::stopForUserCancel): Added iOS-specific code and FIXME comment.
+        (WebCore::FrameLoader::commitProvisionalLoad): Added iOS-specific code and FIXME comment.
+        (WebCore::FrameLoader::transitionToCommitted): Opt out of ENABLE(TOUCH_EVENTS) logic when building for iOS.
+        (WebCore::FrameLoader::didFirstLayout): Added iOS-specific code.
+        (WebCore::FrameLoader::connectionProperties): Added; guarded by PLATFORM(IOS).
+        (WebCore::createWindow): Added iOS-specific code and FIXME comment.
+        * loader/FrameLoader.h:
+        (WebCore::FrameLoader::setLoadsSynchronously): Added.
+        (WebCore::FrameLoader::loadsSynchronously): Added.
+        * loader/FrameLoaderClient.h:
+        * loader/HistoryController.cpp:
+        (WebCore::HistoryController::restoreScrollPositionAndViewState): Opt out of scroll position logic when building for iOS.
+        (WebCore::HistoryController::replaceCurrentItem): Added.
+        * loader/HistoryController.h:
+        * loader/PlaceholderDocument.h: Changed access control of constructor from private to protected and removed the FINAL
+        keyword from the class so that we can subclass PlaceholderDocument on iOS.
+        * loader/PolicyChecker.cpp:
+        (WebCore::PolicyChecker::checkNavigationPolicy): Added USE(QUICK_LOOK)- and USE(CONTENT_FILTERING)-guarded code.
+        * loader/ResourceBuffer.cpp:
+        (WebCore::ResourceBuffer::shouldUsePurgeableMemory): Added; guarded by PLATFORM(IOS).
+        * loader/ResourceBuffer.h:
+        * loader/ResourceLoadNotifier.cpp:
+        (WebCore::ResourceLoadNotifier::dispatchWillSendRequest): Added USE(QUICK_LOOK)-guarded code.
+        * loader/ResourceLoadScheduler.cpp:
+        (WebCore::ResourceLoadScheduler::scheduleSubresourceLoad): Added iOS-specific code.
+        (WebCore::ResourceLoadScheduler::scheduleLoad): Ditto.
+        (WebCore::ResourceLoadScheduler::remove): Added iOS-specific code with FIXME comment.
+        (WebCore::ResourceLoadScheduler::crossOriginRedirectReceived): Added null-check for variable oldHost. Also added
+        iOS-specific code.
+        (WebCore::ResourceLoadScheduler::servePendingRequests): Added iOS-specific code.
+        * loader/ResourceLoader.cpp:
+        (WebCore::ResourceLoader::init): Ditto.
+        (WebCore::ResourceLoader::willSendRequest): Ditto.
+        (WebCore::ResourceLoader::connectionProperties): Added; guarded by PLATFORM(IOS).
+        * loader/ResourceLoader.h:
+        (WebCore::ResourceLoader::startLoading): Added; guarded by PLATFORM(IOS).
+        (WebCore::ResourceLoader::iOSOriginalRequest): Added; iOS-specific.
+        * loader/SubframeLoader.cpp:
+        (WebCore::SubframeLoader::loadPlugin): Added iOS-specific code.
+        * loader/SubresourceLoader.cpp:
+        (WebCore::SubresourceLoader::create): Ditto.
+        (WebCore::SubresourceLoader::startLoading): Added; guarded by PLATFORM(IOS).
+        (WebCore::SubresourceLoader::didFinishLoading): Added iOS-specific code.
+        (WebCore::SubresourceLoader::willCancel): Ditto.
+        (WebCore::SubresourceLoader::notifyDone): Ditto.
+        (WebCore::SubresourceLoader::releaseResources): Ditto.
+        * loader/SubresourceLoader.h:
+        * loader/appcache/ApplicationCacheStorage.cpp:
+        (WebCore::ApplicationCacheStorage::loadCacheGroup): Added iOS-specific code.
+        (WebCore::ApplicationCacheStorage::loadManifestHostHashes): Ditto.
+        (WebCore::ApplicationCacheStorage::cacheGroupForURL): Ditto.
+        (WebCore::ApplicationCacheStorage::fallbackCacheGroupForURL): Ditto.
+        (WebCore::ApplicationCacheStorage::calculateQuotaForOrigin): Ditto.
+        (WebCore::ApplicationCacheStorage::calculateUsageForOrigin): Ditto.
+        (WebCore::ApplicationCacheStorage::calculateRemainingSizeForOriginExcludingCache): Ditto.
+        (WebCore::ApplicationCacheStorage::storeUpdatedQuotaForOrigin): Ditto.
+        (WebCore::ApplicationCacheStorage::executeSQLCommand): Ditto.
+        (WebCore::ApplicationCacheStorage::verifySchemaVersion): Ditto.
+        (WebCore::ApplicationCacheStorage::openDatabase): Ditto.
+        (WebCore::ApplicationCacheStorage::executeStatement): Ditto.
+        (WebCore::ApplicationCacheStorage::store): Ditto.
+        (WebCore::ApplicationCacheStorage::storeUpdatedType): Ditto.
+        (WebCore::ApplicationCacheStorage::ensureOriginRecord): Ditto.
+        (WebCore::ApplicationCacheStorage::loadCache): Ditto.
+        (WebCore::ApplicationCacheStorage::remove): Ditto.
+        (WebCore::ApplicationCacheStorage::empty): Ditto.
+        (WebCore::ApplicationCacheStorage::storeCopyOfCache): Ditto.
+        (WebCore::ApplicationCacheStorage::manifestURLs): Ditto.
+        (WebCore::ApplicationCacheStorage::cacheGroupSize): Ditto.
+        (WebCore::ApplicationCacheStorage::deleteCacheGroup): Ditto.
+        (WebCore::ApplicationCacheStorage::vacuumDatabaseFile): Ditto.
+        * loader/cache/CachedImage.cpp:
+        (WebCore::CachedImage::CachedImage): Added.
+        (WebCore::CachedImage::imageSizeForRenderer): Added iOS-specific code.
+        (WebCore::CachedImageManual::CachedImageManual): Added; guarded by USE(CF). Also added FIXME comment to incorporate
+        the functionality of this class into CachedImage and to remove the USE(CF)-guard once we make MemoryCache::addImageToCache()
+        platform-independent.
+        (WebCore::CachedImageManual::mustRevalidateDueToCacheHeaders): Added; guarded by USE(CF).
+        * loader/cache/CachedImage.h: Removed FINAL keyword from class so that we can define derived class CachedImageManual.
+        (WebCore::CachedImage::isManual): Added; guarded by USE(CF). Also added FIXME comment.
+        (WebCore::CachedImageManual::addFakeClient): Added; guarded by USE(CF).
+        (WebCore::CachedImageManual::removeFakeClient): Added; guarded by USE(CF).
+        * loader/cache/CachedResource.cpp:
+        (WebCore::CachedResource::load): Added iOS-specific code.
+        * loader/cache/CachedResource.h:
+        * loader/cache/CachedResourceLoader.cpp:
+        (WebCore::CachedResourceLoader::loadDone): Added argument shouldPerformPostLoadActions, defaults to true. Modified
+        to conditionally call performPostLoadActions() with respect to the argument shouldPerformPostLoadActions.
+        (WebCore::CachedResourceLoader::preload): Added iOS-specific code.
+        (WebCore::CachedResourceLoader::checkForPendingPreloads): Ditto.
+        * loader/cache/CachedResourceLoader.h:
+        * loader/cache/MemoryCache.cpp:
+        (WebCore::memoryCache):
+        (WebCore::MemoryCache::add): Added iOS-specific code.
+        (WebCore::MemoryCache::revalidationFailed): Ditto.
+        (WebCore::MemoryCache::resourceForRequest): Ditto.
+        (WebCore::MemoryCache::addImageToCache): Added; guarded by USE(CF). Also added FIXME comment.
+        (WebCore::MemoryCache::removeImageFromCache): Added; guarded by USE(CF). Also added FIXME comment.
+        (WebCore::MemoryCache::pruneLiveResources): Modified to take argument shouldDestroyDecodedDataForAllLiveResources.
+        (WebCore::MemoryCache::pruneLiveResourcesToSize): Modified to take argument shouldDestroyDecodedDataForAllLiveResources,
+        defaults to false. When this argument is true we destroy the decoded data for all live resources from the memory cache.
+        Such functionality is useful when the system is running low on memory.
+        (WebCore::MemoryCache::evict): Added iOS-specific code.
+        * loader/cache/MemoryCache.h:
+        * loader/cf/SubresourceLoaderCF.cpp:
+        (WebCore::SubresourceLoader::didReceiveDataArray): Actually make this code compile. In particular, there is no
+        method called sendDataToResource on SubresourceLoader or in its class hierarchy.
+        * loader/mac/DocumentLoaderMac.cpp:
+        (WebCore::DocumentLoader::schedule): This method has an empty implementation when building for iOS.
+        (WebCore::DocumentLoader::unschedule): Ditto.
+        * platform/graphics/BitmapImage.h: Exposed decodedSize() to access the decoded size of the bitmap image.
+        This functionality is used in MemoryCache::addImageToCache().
+
 2013-12-19  Jer Noble  <jer.noble@apple.com>
 
         Build fix for platforms which do not define -[AVSampleBufferAudioRenderer muted].
index 77b8223..61bf8ba 100644 (file)
@@ -174,8 +174,10 @@ __ZN7WebCore11MemoryCache13getStatisticsEv
 __ZN7WebCore11MemoryCache13setCapacitiesEjjj
 __ZN7WebCore11MemoryCache14evictResourcesEv
 __ZN7WebCore11MemoryCache14resourceForURLERKNS_3URLE
+__ZN7WebCore11MemoryCache15addImageToCacheEP7CGImageRKNS_3URLERKN3WTF6StringE
 __ZN7WebCore11MemoryCache18resourceForRequestERKNS_15ResourceRequestE
 __ZN7WebCore11MemoryCache19getOriginsWithCacheERN3WTF7HashSetINS1_6RefPtrINS_14SecurityOriginEEENS_18SecurityOriginHashENS1_10HashTraitsIS5_EEEE
+__ZN7WebCore11MemoryCache20removeImageFromCacheERKNS_3URLERKN3WTF6StringE
 __ZN7WebCore11MemoryCache25removeResourcesWithOriginEPNS_14SecurityOriginE
 __ZN7WebCore11PageConsole21shouldPrintExceptionsEv
 __ZN7WebCore11PageConsole24setShouldPrintExceptionsEb
index 32bd815..ba9cb0a 100644 (file)
 #include "PolicyChecker.h"
 #include "ProgressTracker.h"
 #include "ResourceBuffer.h"
+#include "ResourceHandle.h"
 #include "SchemeRegistry.h"
 #include "SecurityPolicy.h"
 #include "Settings.h"
 #include "SubresourceLoader.h"
 #include "TextResourceDecoder.h"
 #include <wtf/Assertions.h>
+#include <wtf/NeverDestroyed.h>
 #include <wtf/Ref.h>
 #include <wtf/text/CString.h>
 #include <wtf/text/WTFString.h>
@@ -95,6 +97,26 @@ static void setAllDefersLoading(const ResourceLoaderSet& loaders, bool defers)
         loadersCopy[i]->setDefersLoading(defers);
 }
 
+static bool areAllLoadersPageCacheAcceptable(const ResourceLoaderSet& loaders)
+{
+    Vector<RefPtr<ResourceLoader>> loadersCopy;
+    copyToVector(loaders, loadersCopy);
+    for (auto& loader : loadersCopy) {
+        ResourceHandle* handle = loader->handle();
+        if (!handle)
+            return false;
+
+        CachedResource* cachedResource = memoryCache()->resourceForURL(handle->firstRequest().url());
+        if (!cachedResource)
+            return false;
+
+        // All non-image loads will prevent the page from entering the PageCache.
+        if (!cachedResource->isImage())
+            return false;
+    }
+    return true;
+}
+
 DocumentLoader::DocumentLoader(const ResourceRequest& req, const SubstituteData& substituteData)
     : m_deferMainResourceDataLoad(true)
     , m_frame(0)
@@ -119,6 +141,7 @@ DocumentLoader::DocumentLoader(const ResourceRequest& req, const SubstituteData&
     , m_identifierForLoadWithoutResourceLoader(0)
     , m_dataLoadTimer(this, &DocumentLoader::handleSubstituteDataLoadNow)
     , m_waitingForContentPolicy(false)
+    , m_subresourceLoadersArePageCacheAcceptable(false)
     , m_applicationCacheHost(adoptPtr(new ApplicationCacheHost(this)))
 {
 }
@@ -256,7 +279,14 @@ void DocumentLoader::stopLoading()
     // (This can happen when there's a single XMLHttpRequest currently loading and stopLoading causes it
     // to stop loading. Because of this, we need to save it so we don't return early.
     bool loading = isLoading();
-    
+
+    // We may want to audit the existing subresource loaders when we are on a page which has completed
+    // loading but there are subresource loads during cancellation. This must be done before the
+    // frame->stopLoading() call, which may evict the CachedResources, which we rely on to check
+    // the type of the resource loads.
+    if (loading && m_committed && !mainResourceLoader() && !m_subresourceLoaders.isEmpty())
+        m_subresourceLoadersArePageCacheAcceptable = areAllLoadersPageCacheAcceptable(m_subresourceLoaders);
+
     if (m_committed) {
         // Attempt to stop the frame if the document loader is loading, or if it is done loading but
         // still  parsing. Failure to do so can cause a world leak.
@@ -381,6 +411,9 @@ void DocumentLoader::finishedLoading(double finishTime)
         const char* data = m_contentFilter->getReplacementData(length);
         if (data)
             dataReceived(m_mainResource.get(), data, length);
+
+        if (m_contentFilter->didBlockData())
+            setContentFilterForBlockedLoad(m_contentFilter);
     }
 #endif
 
@@ -455,10 +488,10 @@ void DocumentLoader::startDataLoadTimer()
 
 void DocumentLoader::handleSubstituteDataLoadSoon()
 {
-    if (m_deferMainResourceDataLoad)
-        startDataLoadTimer();
-    else
+    if (!m_deferMainResourceDataLoad || frameLoader()->loadsSynchronously())
         handleSubstituteDataLoadNow(0);
+    else
+        startDataLoadTimer();
 }
 
 void DocumentLoader::redirectReceived(CachedResource* resource, ResourceRequest& request, const ResourceResponse& redirectResponse)
@@ -633,7 +666,7 @@ void DocumentLoader::responseReceived(CachedResource* resource, const ResourceRe
 #endif
 
 #if USE(CONTENT_FILTERING)
-    if (response.url().protocolIs("https") && ContentFilter::isEnabled())
+    if (response.url().protocolIsInHTTPFamily() && ContentFilter::isEnabled())
         m_contentFilter = ContentFilter::create(response);
 #endif
 
@@ -844,6 +877,9 @@ void DocumentLoader::dataReceived(CachedResource* resource, const char* data, in
 
         data = m_contentFilter->getReplacementData(length);
         loadWasBlockedBeforeFinishing = m_contentFilter->didBlockData();
+
+        if (loadWasBlockedBeforeFinishing)
+            setContentFilterForBlockedLoad(m_contentFilter);
     }
 #endif
 
@@ -927,6 +963,12 @@ void DocumentLoader::detachFromFrame()
 void DocumentLoader::clearMainResourceLoader()
 {
     m_loadingMainResource = false;
+
+#if PLATFORM(IOS)
+    // FIXME: Remove PLATFORM(IOS)-guard once we upstream the iOS changes to ResourceRequest.h.
+    m_request.setMainResourceRequest(false);
+#endif
+
     if (this == frameLoader()->activeDocumentLoader())
         checkLoadComplete();
 }
@@ -1256,6 +1298,14 @@ const String& DocumentLoader::responseMIMEType() const
     return m_response.mimeType();
 }
 
+#if PLATFORM(IOS)
+// FIXME: This method seems to violate the encapsulation of this class.
+void DocumentLoader::setResponseMIMEType(const String& responseMimeType)
+{
+    m_response.setMimeType(responseMimeType);
+}
+#endif
+
 const URL& DocumentLoader::unreachableURL() const
 {
     return m_substituteData.failingURL();
@@ -1380,9 +1430,13 @@ void DocumentLoader::startLoadingMainResource()
         return;
     }
 
+#if PLATFORM(IOS)
+    // FIXME: Remove PLATFORM(IOS)-guard once we upstream the iOS changes to ResourceRequest.h.
+    m_request.setMainResourceRequest(true);
+#endif
+
     ResourceRequest request(m_request);
-    DEFINE_STATIC_LOCAL(ResourceLoaderOptions, mainResourceLoadOptions,
-        (SendCallbacks, SniffContent, BufferData, AllowStoredCredentials, AskClientForAllCredentials, SkipSecurityCheck, UseDefaultOriginRestrictionsForType));
+    static NeverDestroyed<ResourceLoaderOptions> mainResourceLoadOptions(SendCallbacks, SniffContent, BufferData, AllowStoredCredentials, AskClientForAllCredentials, SkipSecurityCheck, UseDefaultOriginRestrictionsForType);
     CachedResourceRequest cachedResourceRequest(request, mainResourceLoadOptions);
     m_mainResource = m_cachedResourceLoader->requestMainResource(cachedResourceRequest);
     if (!m_mainResource) {
@@ -1506,4 +1560,38 @@ void DocumentLoader::handledOnloadEvents()
     applicationCacheHost()->stopDeferringEvents();
 }
 
+#if USE(CONTENT_FILTERING)
+void DocumentLoader::setContentFilterForBlockedLoad(PassRefPtr<ContentFilter> contentFilter)
+{
+    ASSERT(!m_contentFilterForBlockedLoad);
+    ASSERT(contentFilter);
+    ASSERT(contentFilter->didBlockData());
+    m_contentFilterForBlockedLoad = contentFilter;
+}
+
+bool DocumentLoader::handleContentFilterRequest(const ResourceRequest& request)
+{
+    // FIXME: Remove PLATFORM(IOS)-guard once we upstream ContentFilterIOS.mm and
+    // implement ContentFilter::requestUnblockAndDispatchIfSuccessful() for Mac.
+#if PLATFORM(IOS)
+    if (!m_contentFilterForBlockedLoad)
+        return false;
+
+    if (!request.url().protocolIs(ContentFilter::scheme()))
+        return false;
+
+    if (equalIgnoringCase(request.url().host(), "unblock")) {
+        // Tell the FrameLoader to reload if the unblock is successful.
+        m_contentFilterForBlockedLoad->requestUnblockAndDispatchIfSuccessful(bind(&FrameLoader::reload, &(m_frame->loader()), false));
+        return true;
+    }
+
+    return false;
+#else
+    UNUSED_PARAM(request);
+    return false;
+#endif
+}
+#endif
+
 } // namespace WebCore
index 33386e6..151d369 100644 (file)
@@ -116,6 +116,10 @@ namespace WebCore {
         const URL& requestURL() const;
         const URL& responseURL() const;
         const String& responseMIMEType() const;
+#if PLATFORM(IOS)
+        // FIXME: This method seems to violate the encapsulation of this class.
+        void setResponseMIMEType(const String&);
+#endif
 
         void replaceRequestURLForSameDocumentNavigation(const URL&);
         bool isStopping() const { return m_isStopping; }
@@ -123,8 +127,15 @@ namespace WebCore {
         void setCommitted(bool committed) { m_committed = committed; }
         bool isCommitted() const { return m_committed; }
         bool isLoading() const;
-        const ResourceResponse& response() const { return m_response; }
+
         const ResourceError& mainDocumentError() const { return m_mainDocumentError; }
+
+        const ResourceResponse& response() const { return m_response; }
+#if PLATFORM(IOS)
+        // FIXME: This method seems to violate the encapsulation of this class.
+        void setResponse(const ResourceResponse& response) { m_response = response; }
+#endif
+
         bool isClientRedirect() const { return m_isClientRedirect; }
         void setIsClientRedirect(bool isClientRedirect) { m_isClientRedirect = isClientRedirect; }
         void handledOnloadEvents();
@@ -193,7 +204,9 @@ namespace WebCore {
 
         bool didCreateGlobalHistoryEntry() const { return m_didCreateGlobalHistoryEntry; }
         void setDidCreateGlobalHistoryEntry(bool didCreateGlobalHistoryEntry) { m_didCreateGlobalHistoryEntry = didCreateGlobalHistoryEntry; }
-        
+
+        bool subresourceLoadersArePageCacheAcceptable() const { return m_subresourceLoadersArePageCacheAcceptable; }
+
         void setDefersLoading(bool);
         void setMainResourceDataBufferingPolicy(DataBufferingPolicy);
 
@@ -249,15 +262,20 @@ namespace WebCore {
 
         void checkLoadComplete();
 
+#if USE(CONTENT_FILTERING)
+        void setContentFilterForBlockedLoad(PassRefPtr<ContentFilter>);
+        bool handleContentFilterRequest(const ResourceRequest&);
+#endif
+
+        // The URL of the document resulting from this DocumentLoader.
+        URL documentURL() const;
+
     protected:
         DocumentLoader(const ResourceRequest&, const SubstituteData&);
 
         bool m_deferMainResourceDataLoad;
 
     private:
-
-        // The URL of the document resulting from this DocumentLoader.
-        URL documentURL() const;
         Document* document() const;
 
         void setRequest(const ResourceRequest&);
@@ -397,11 +415,14 @@ namespace WebCore {
         RefPtr<IconLoadDecisionCallback> m_iconLoadDecisionCallback;
         RefPtr<IconDataCallback> m_iconDataCallback;
 
+        bool m_subresourceLoadersArePageCacheAcceptable;
+
         friend class ApplicationCacheHost;  // for substitute resource delivery
         OwnPtr<ApplicationCacheHost> m_applicationCacheHost;
 
 #if USE(CONTENT_FILTERING)
         RefPtr<ContentFilter> m_contentFilter;
+        RefPtr<ContentFilter> m_contentFilterForBlockedLoad;
 #endif
     };
 
index 6a6d3b0..9356244 100644 (file)
 #include "TextResourceDecoder.h"
 #include <wtf/Ref.h>
 
+#if PLATFORM(IOS)
+#include "PDFDocument.h"
+#endif
+
 namespace WebCore {
 
 static inline bool canReferToParentFrameEncoding(const Frame* frame, const Frame* parentFrame) 
@@ -107,6 +111,10 @@ PassRefPtr<Document> DocumentWriter::createDocument(const URL& url)
 {
     if (!m_frame->loader().stateMachine()->isDisplayingInitialEmptyDocument() && m_frame->loader().client().shouldAlwaysUsePluginDocument(m_mimeType))
         return PluginDocument::create(m_frame, url);
+#if PLATFORM(IOS)
+    if (equalIgnoringCase(m_mimeType, "application/pdf"))
+        return PDFDocument::create(m_frame, url);
+#endif
     if (!m_frame->loader().client().hasHTMLView())
         return PlaceholderDocument::create(m_frame, url);
     return DOMImplementation::createDocument(m_mimeType, m_frame, url, m_frame->inViewSourceMode());
index fc24acb..b638d1c 100644 (file)
@@ -104,10 +104,10 @@ PassOwnPtr<ColorChooser> EmptyChromeClient::createColorChooser(ColorChooserClien
 }
 #endif
 
-#if ENABLE(DATE_AND_TIME_INPUT_TYPES)
+#if ENABLE(DATE_AND_TIME_INPUT_TYPES) && !PLATFORM(IOS)
 PassRefPtr<DateTimeChooser> EmptyChromeClient::openDateTimeChooser(DateTimeChooserClient*, const DateTimeChooserParameters&)
 {
-    return PassRefPtr<DateTimeChooser>();
+    return nullptr;
 }
 #endif
 
index b015b02..296f41e 100644 (file)
@@ -162,7 +162,7 @@ public:
     virtual PassOwnPtr<ColorChooser> createColorChooser(ColorChooserClient*, const Color&) OVERRIDE;
 #endif
 
-#if ENABLE(DATE_AND_TIME_INPUT_TYPES)
+#if ENABLE(DATE_AND_TIME_INPUT_TYPES) && !PLATFORM(IOS)
     virtual PassRefPtr<DateTimeChooser> openDateTimeChooser(DateTimeChooserClient*, const DateTimeChooserParameters&) OVERRIDE;
 #endif
 
@@ -174,8 +174,10 @@ public:
     virtual void elementDidFocus(const Node*) OVERRIDE { }
     virtual void elementDidBlur(const Node*) OVERRIDE { }
 
+#if !PLATFORM(IOS)
     virtual void setCursor(const Cursor&) OVERRIDE { }
     virtual void setCursorHiddenUntilMouseMoves(bool) OVERRIDE { }
+#endif
 
     virtual void scrollRectIntoView(const IntRect&) const OVERRIDE { }
 
@@ -192,6 +194,28 @@ public:
 #endif
 
 #if PLATFORM(IOS)
+#if ENABLE(TOUCH_EVENTS)
+    virtual void didPreventDefaultForEvent() OVERRIDE { }
+#endif
+    virtual void didReceiveMobileDocType() OVERRIDE { }
+    virtual void setNeedsScrollNotifications(Frame*, bool) OVERRIDE { }
+    virtual void observedContentChange(Frame*) OVERRIDE { }
+    virtual void clearContentChangeObservers(Frame*) OVERRIDE { }
+    virtual void notifyRevealedSelectionByScrollingFrame(Frame*) OVERRIDE { }
+    virtual void didLayout(LayoutType) OVERRIDE { }
+    virtual void didStartOverflowScroll() OVERRIDE { }
+    virtual void didEndOverflowScroll() OVERRIDE { }
+
+    virtual void suppressFormNotifications() OVERRIDE { }
+    virtual void restoreFormNotifications() OVERRIDE { }
+
+    virtual void addOrUpdateScrollingLayer(Node*, PlatformLayer*, PlatformLayer*, const IntSize&, bool, bool) OVERRIDE { }
+    virtual void removeScrollingLayer(Node*, PlatformLayer*, PlatformLayer*) OVERRIDE { }
+
+    virtual void webAppOrientationsUpdated() OVERRIDE { };
+#endif // PLATFORM(IOS)
+
+#if PLATFORM(IOS)
     virtual bool isStopping() OVERRIDE { return false; }
 #endif
 
@@ -220,6 +244,9 @@ public:
 
     virtual void makeRepresentation(DocumentLoader*) OVERRIDE { }
     virtual void forceLayout() OVERRIDE { }
+#if PLATFORM(IOS)
+    virtual void forceLayoutWithoutRecalculatingStyles() OVERRIDE { }
+#endif
     virtual void forceLayoutForNonHTML() OVERRIDE { }
 
     virtual void setCopiesOnScroll() OVERRIDE { }
@@ -237,6 +264,11 @@ public:
 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
     virtual bool canAuthenticateAgainstProtectionSpace(DocumentLoader*, unsigned long, const ProtectionSpace&) OVERRIDE { return false; }
 #endif
+
+#if PLATFORM(IOS)
+    virtual RetainPtr<CFDictionaryRef> connectionProperties(DocumentLoader*, unsigned long) OVERRIDE { return nullptr; }
+#endif
+
     virtual void dispatchDidReceiveResponse(DocumentLoader*, unsigned long, const ResourceResponse&) OVERRIDE { }
     virtual void dispatchDidReceiveContentLength(DocumentLoader*, unsigned long, int) OVERRIDE { }
     virtual void dispatchDidFinishLoading(DocumentLoader*, unsigned long) OVERRIDE { }
@@ -325,6 +357,9 @@ public:
 
     virtual void savePlatformDataToCachedFrame(CachedFrame*) OVERRIDE { }
     virtual void transitionToCommittedFromCachedFrame(CachedFrame*) OVERRIDE { }
+#if PLATFORM(IOS)
+    virtual void didRestoreFrameHierarchyForCachedFrame() OVERRIDE { }
+#endif
     virtual void transitionToCommittedForNewPage() OVERRIDE { }
 
     virtual void didSaveToPageCache() OVERRIDE { }
@@ -449,6 +484,21 @@ public:
     virtual void textWillBeDeletedInTextField(Element*) OVERRIDE { }
     virtual void textDidChangeInTextArea(Element*) OVERRIDE { }
 
+#if PLATFORM(IOS)
+    virtual void suppressSelectionNotifications() OVERRIDE { }
+    virtual void restoreSelectionNotifications() OVERRIDE { }
+    virtual void startDelayingAndCoalescingContentChangeNotifications() OVERRIDE { }
+    virtual void stopDelayingAndCoalescingContentChangeNotifications() OVERRIDE { }
+    virtual void writeDataToPasteboard(NSDictionary*) OVERRIDE { }
+    virtual NSArray* supportedPasteboardTypesForCurrentSelection() OVERRIDE { return nullptr; }
+    virtual NSArray* readDataFromPasteboard(NSString*, int) OVERRIDE { return nullptr; }
+    virtual bool hasRichlyEditableSelection() OVERRIDE { return false; }
+    virtual int getPasteboardItemsCount() OVERRIDE { return 0; }
+    virtual DocumentFragment* documentFragmentFromDelegate(int) OVERRIDE { return nullptr; }
+    virtual bool performsTwoStepPaste(DocumentFragment*) OVERRIDE { return false; }
+    virtual int pasteboardChangeCount() OVERRIDE { return 0; }
+#endif
+
 #if PLATFORM(MAC)
     virtual NSString* userVisibleString(NSURL*) OVERRIDE { return 0; }
     virtual DocumentFragment* documentFragmentFromAttributedString(NSAttributedString*, Vector<RefPtr<ArchiveResource>>&) OVERRIDE { return 0; };
index ab1af3e..d9c6612 100644 (file)
 #include "Archive.h"
 #endif
 
+#if PLATFORM(IOS)
+#include "DocumentType.h"
+#include "MemoryPressureHandler.h"
+#include "ResourceLoader.h"
+#include "RuntimeApplicationChecksIOS.h"
+#include "SystemMemory.h"
+#include "WKContentObservation.h"
+#endif
 
 namespace WebCore {
 
@@ -144,6 +152,10 @@ using namespace SVGNames;
 static const char defaultAcceptHeader[] = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
 static double storedTimeOfLastCompletedLoad;
 
+#if PLATFORM(IOS)
+const int memoryLevelThresholdToPrunePageCache = 20;
+#endif
+
 bool isBackForwardLoadType(FrameLoadType type)
 {
     switch (type) {
@@ -239,6 +251,7 @@ FrameLoader::FrameLoader(Frame& frame, FrameLoaderClient& client)
     , m_loadingFromCachedPage(false)
     , m_suppressOpenerInNewFrame(false)
     , m_currentNavigationHasShownBeforeUnloadConfirmPanel(false)
+    , m_loadsSynchronously(false)
     , m_forcedSandboxFlags(SandboxNone)
 {
 }
@@ -270,6 +283,32 @@ void FrameLoader::init()
     m_progressTracker = std::make_unique<FrameProgressTracker>(m_frame);
 }
 
+#if PLATFORM(IOS)
+void FrameLoader::initForSynthesizedDocument(const URL&)
+{
+    // FIXME: We need to initialize the document URL to the specified URL. Currently the URL is empty and hence
+    // FrameLoader::checkCompleted() will overwrite the URL of the document to be activeDocumentLoader()->documentURL().
+
+    RefPtr<DocumentLoader> loader = m_client.createDocumentLoader(ResourceRequest(URL(ParsedURLString, emptyString())), SubstituteData());
+    loader->setFrame(&m_frame);
+    loader->setResponse(ResourceResponse(URL(), ASCIILiteral("text/html"), 0, String(), String()));
+    loader->setCommitted(true);
+    setDocumentLoader(loader.get());
+
+    m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocument);
+    m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit);
+    m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
+    m_client.transitionToCommittedForNewPage();
+
+    m_didCallImplicitClose = true;
+    m_isComplete = true;
+    m_state = FrameStateComplete;
+    m_needsClear = true;
+
+    m_networkingContext = m_client.createNetworkingContext();
+}
+#endif
+
 void FrameLoader::setDefersLoading(bool defers)
 {
     if (m_documentLoader)
@@ -789,6 +828,18 @@ void FrameLoader::checkCompleted()
     m_requestedHistoryItem = 0;
     m_frame.document()->setReadyState(Document::Complete);
 
+#if PLATFORM(IOS)
+    if (m_frame.document()->url().isEmpty()) {
+        // We need to update the document URL of a PDF document to be non-empty so that both back/forward history navigation
+        // between PDF pages and fragment navigation works. See <rdar://problem/9544769> for more details.
+        // FIXME: Is there a better place for this code, say DocumentLoader? Also, we should explicitly only update the URL
+        // of the document when it's a PDFDocument object instead of assuming that a Document object with an empty URL is a PDFDocument.
+        // FIXME: This code is incorrect for a synthesized document (which also has an empty URL). The URL for a synthesized
+        // document should be the URL specified to FrameLoader::initForSynthesizedDocument().
+        m_frame.document()->setURL(activeDocumentLoader()->documentURL());
+    }
+#endif
+
     checkCallImplicitClose(); // if we didn't do it before
 
     m_frame.navigationScheduler().startTimer();
@@ -1451,6 +1502,13 @@ const ResourceRequest& FrameLoader::initialRequest() const
 
 bool FrameLoader::willLoadMediaElementURL(URL& url)
 {
+#if PLATFORM(IOS)
+    // MobileStore depends on the iOS 4.0 era client delegate method because webView:resource:willSendRequest:redirectResponse:fromDataSource
+    // doesn't let them tell when a load request is coming from a media element. See <rdar://problem/8266916> for more details.
+    if (applicationIsMobileStore())
+        return m_client.shouldLoadMediaElementURL(url);
+#endif
+
     ResourceRequest request(url);
 
     unsigned long identifier;
@@ -1603,7 +1661,15 @@ void FrameLoader::stopAllLoaders(ClearProvisionalItemPolicy clearProvisionalItem
 void FrameLoader::stopForUserCancel(bool deferCheckLoadComplete)
 {
     stopAllLoaders();
-    
+
+#if PLATFORM(IOS)
+    // Lay out immediately when stopping to immediately clear the old page if we just committed this one
+    // but haven't laid out/painted yet.
+    // FIXME: Is this behavior specific to iOS? Or should we expose a setting to toggle this behavior?
+    if (m_frame.view() && !m_frame.view()->didFirstLayout())
+        m_frame.view()->layout();
+#endif
+
     if (deferCheckLoadComplete)
         scheduleCheckLoadComplete();
     else if (m_frame.page())
@@ -1722,6 +1788,26 @@ void FrameLoader::commitProvisionalLoad()
         m_frame.document() ? m_frame.document()->url().stringCenterEllipsizedToLength().utf8().data() : "",
         pdl ? pdl->url().stringCenterEllipsizedToLength().utf8().data() : "<no provisional DocumentLoader>");
 
+#if PLATFORM(IOS)
+    // In the case where we are not navigating to a cached page, and the system is under (speculative) memory pressure,
+    // we can try to preemptively release some of the pages in the cache.
+    // FIXME: Right now the capacity is 1 on iOS devices with 256 MB of RAM, so this will always blow away the whole
+    // page cache. We could still preemptively prune the page cache while navigating to a cached page if capacity > 1.
+    // See <rdar://problem/11779846> for more details.
+    if (!cachedPage) {
+        if (memoryPressureHandler().hasReceivedMemoryPressure()) {
+            LOG(MemoryPressure, "Pruning page cache because under memory pressure at: %s", __PRETTY_FUNCTION__);
+            LOG(PageCache, "Pruning page cache to 0 due to memory pressure");
+            // Don't cache any page if we are under memory pressure.
+            pageCache()->pruneToCapacityNow(0);
+        } else if (systemMemoryLevel() <= memoryLevelThresholdToPrunePageCache) {
+            LOG(MemoryPressure, "Pruning page cache because system memory level is %d at: %s", systemMemoryLevel(), __PRETTY_FUNCTION__);
+            LOG(PageCache, "Pruning page cache to %d due to low memory (level %d less or equal to %d threshold)", pageCache()->capacity() / 2, systemMemoryLevel(), memoryLevelThresholdToPrunePageCache);
+            pageCache()->pruneToCapacityNow(pageCache()->capacity() / 2);
+        }
+    }
+#endif
+
     willTransitionToCommitted();
 
     // Check to see if we need to cache the page we are navigating away from into the back/forward cache.
@@ -1752,13 +1838,21 @@ void FrameLoader::commitProvisionalLoad()
         clientRedirectCancelledOrFinished(false);
     
     if (cachedPage && cachedPage->document()) {
+#if PLATFORM(IOS)
+        // FIXME: CachedPage::restore() would dispatch viewport change notification. However UIKit expects load
+        // commit to happen before any changes to viewport arguments and dealing with this there is difficult.
+        m_frame.page()->chrome().setDispatchViewportDataDidChangeSuppressed(true);
+#endif
         prepareForCachedPageRestore();
 
         // FIXME: This API should be turned around so that we ground CachedPage into the Page.
         cachedPage->restore(*m_frame.page());
 
         dispatchDidCommitLoad();
-
+#if PLATFORM(IOS)
+        m_frame.page()->chrome().setDispatchViewportDataDidChangeSuppressed(false);
+        m_frame.page()->chrome().dispatchViewportPropertiesDidChange(m_frame.page()->viewportArguments());
+#endif
         // If we have a title let the WebView know about it. 
         StringWithDirection title = m_documentLoader->title();
         if (!title.isNull())
@@ -1775,10 +1869,19 @@ void FrameLoader::commitProvisionalLoad()
         history().updateForClientRedirect();
 
     if (m_loadingFromCachedPage) {
+#if PLATFORM(IOS)
+        // Note, didReceiveDocType is expected to be called for cached pages. See <rdar://problem/5906758> for more details.
+        if (m_frame.document()->doctype() && m_frame.page())
+            m_frame.page()->chrome().didReceiveDocType(&m_frame);
+#endif
         m_frame.document()->documentDidResumeFromPageCache();
-        
+
         // Force a layout to update view size and thereby update scrollbars.
+#if PLATFORM(IOS)
+        m_client.forceLayoutWithoutRecalculatingStyles();
+#else
         m_frame.view()->forceLayout();
+#endif
 
         const ResponseVector& responses = m_documentLoader->responses();
         size_t count = responses.size();
@@ -1841,7 +1944,7 @@ void FrameLoader::transitionToCommitted(CachedPage* cachedPage)
 
     setState(FrameStateCommittedPage);
 
-#if ENABLE(TOUCH_EVENTS)
+#if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
     if (m_frame.isMainFrame())
         m_frame.page()->chrome().client().needTouchEvents(false);
 #endif
@@ -2299,6 +2402,13 @@ void FrameLoader::didLayout(LayoutMilestones milestones)
 
 void FrameLoader::didFirstLayout()
 {
+#if PLATFORM(IOS)
+    // Only send layout-related delegate callbacks synchronously for the main frame to
+    // avoid reentering layout for the main frame while delivering a layout-related delegate
+    // callback for a subframe.
+    if (&m_frame != &m_frame.page()->mainFrame())
+        return;
+#endif
     if (m_frame.page() && isBackForwardLoadType(m_loadType))
         history().restoreScrollPositionAndViewState();
 
@@ -3252,6 +3362,13 @@ ResourceError FrameLoader::cancelledError(const ResourceRequest& request) const
     return error;
 }
 
+#if PLATFORM(IOS)
+RetainPtr<CFDictionaryRef> FrameLoader::connectionProperties(ResourceLoader* loader)
+{
+    return m_client.connectionProperties(loader->documentLoader(), loader->identifier());
+}
+#endif
+
 String FrameLoader::referrer() const
 {
     return m_documentLoader ? m_documentLoader->request().httpReferrer() : "";
@@ -3463,9 +3580,10 @@ PassRefPtr<Frame> createWindow(Frame* openerFrame, Frame* lookupFrame, const Fra
     // specify the size of the viewport. We can only resize the window, so adjust
     // for the difference between the window size and the viewport size.
 
-    FloatRect windowRect = page->chrome().windowRect();
+// FIXME: We should reconcile the initialization of viewport arguments between iOS and OpenSource.
+#if !PLATFORM(IOS)
     FloatSize viewportSize = page->chrome().pageRect().size();
-
+    FloatRect windowRect = page->chrome().windowRect();
     if (features.xSet)
         windowRect.setX(features.x);
     if (features.ySet)
@@ -3480,6 +3598,17 @@ PassRefPtr<Frame> createWindow(Frame* openerFrame, Frame* lookupFrame, const Fra
     FloatRect newWindowRect = DOMWindow::adjustWindowRect(page, windowRect);
 
     page->chrome().setWindowRect(newWindowRect);
+#else
+    // On iOS, width and height refer to the viewport dimensions.
+    ViewportArguments arguments;
+    // Zero width and height mean using default size, not minimum one.
+    if (features.widthSet && features.width)
+        arguments.width = features.width;
+    if (features.heightSet && features.height)
+        arguments.height = features.height;
+    page->mainFrame().setViewportArguments(arguments);
+#endif
+
     page->chrome().show();
 
     created = true;
index 46328d4..b453fce 100644 (file)
@@ -89,6 +89,9 @@ public:
     ~FrameLoader();
 
     void init();
+#if PLATFORM(IOS)
+    void initForSynthesizedDocument(const URL&);
+#endif
 
     Frame& frame() const { return m_frame; }
 
@@ -155,6 +158,9 @@ public:
     FrameState state() const { return m_state; }
     static double timeOfLastCompletedLoad();
 
+#if PLATFORM(IOS)
+    RetainPtr<CFDictionaryRef> connectionProperties(ResourceLoader*);
+#endif
     const ResourceRequest& originalRequest() const;
     const ResourceRequest& initialRequest() const;
     void receivedMainResourceError(const ResourceError&);
@@ -241,6 +247,9 @@ public:
 
     void commitProvisionalLoad();
 
+    void setLoadsSynchronously(bool loadsSynchronously) { m_loadsSynchronously = loadsSynchronously; }
+    bool loadsSynchronously() const { return m_loadsSynchronously; }
+
     FrameLoaderStateMachine* stateMachine() const { return &m_stateMachine; }
 
     Frame* findFrameForNavigation(const AtomicString& name, Document* activeDocument = 0);
@@ -435,9 +444,11 @@ private:
     bool m_didPerformFirstNavigation;
     bool m_loadingFromCachedPage;
     bool m_suppressOpenerInNewFrame;
-    
+
     bool m_currentNavigationHasShownBeforeUnloadConfirmPanel;
 
+    bool m_loadsSynchronously;
+
     SandboxFlags m_forcedSandboxFlags;
 
     RefPtr<FrameNetworkingContext> m_networkingContext;
index 5dcef7d..fcbbcb7 100644 (file)
@@ -116,6 +116,9 @@ namespace WebCore {
 
         virtual void makeRepresentation(DocumentLoader*) = 0;
         virtual void forceLayout() = 0;
+#if PLATFORM(IOS)
+        virtual void forceLayoutWithoutRecalculatingStyles() = 0;
+#endif
         virtual void forceLayoutForNonHTML() = 0;
 
         virtual void setCopiesOnScroll() = 0;
@@ -132,6 +135,11 @@ namespace WebCore {
 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
         virtual bool canAuthenticateAgainstProtectionSpace(DocumentLoader*, unsigned long identifier, const ProtectionSpace&) = 0;
 #endif
+
+#if PLATFORM(IOS)
+        virtual RetainPtr<CFDictionaryRef> connectionProperties(DocumentLoader*, unsigned long identifier) = 0;
+#endif
+
         virtual void dispatchDidReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse&) = 0;
         virtual void dispatchDidReceiveContentLength(DocumentLoader*, unsigned long identifier, int dataLength) = 0;
         virtual void dispatchDidFinishLoading(DocumentLoader*, unsigned long identifier) = 0;
@@ -249,6 +257,9 @@ namespace WebCore {
         
         virtual void savePlatformDataToCachedFrame(CachedFrame*) = 0;
         virtual void transitionToCommittedFromCachedFrame(CachedFrame*) = 0;
+#if PLATFORM(IOS)
+        virtual void didRestoreFrameHierarchyForCachedFrame() = 0;
+#endif
         virtual void transitionToCommittedForNewPage() = 0;
 
         virtual void didSaveToPageCache() = 0;
@@ -281,7 +292,7 @@ namespace WebCore {
         virtual void didPerformFirstNavigation() const = 0; // "Navigation" here means a transition from one page to another that ends up in the back/forward list.
 
         virtual void registerForIconNotification(bool listen = true) = 0;
-        
+
 #if PLATFORM(MAC)
         // Allow an accessibility object to retrieve a Frame parent if there's no PlatformWidget.
         virtual RemoteAXObjectRef accessibilityRemoteObject() = 0;
index d56598f..ebc1182 100644 (file)
@@ -127,6 +127,8 @@ void HistoryController::restoreScrollPositionAndViewState()
     // through to the client. It's currently used only for the PDF view on Mac.
     m_frame.loader().client().restoreViewState();
 
+    // Don't restore scroll point on iOS as FrameLoaderClient::restoreViewState() does that.
+#if !PLATFORM(IOS)
     // FIXME: There is some scrolling related work that needs to happen whenever a page goes into the
     // page cache and similar work that needs to occur when it comes out. This is where we do the work
     // that needs to happen when we exit, and the work that needs to happen when we enter is in
@@ -146,6 +148,7 @@ void HistoryController::restoreScrollPositionAndViewState()
                 view->setScrollPosition(m_currentItem->scrollPoint());
         }
     }
+#endif
 }
 
 void HistoryController::updateBackForwardListForFragmentScroll()
@@ -875,4 +878,16 @@ void HistoryController::replaceState(PassRefPtr<SerializedScriptValue> stateObje
     m_frame.loader().client().updateGlobalHistory();
 }
 
+void HistoryController::replaceCurrentItem(HistoryItem* item)
+{
+    if (!item)
+        return;
+
+    m_previousItem = nullptr;
+    if (m_provisionalItem)
+        m_provisionalItem = item;
+    else
+        m_currentItem = item;
+}
+
 } // namespace WebCore
index 4a15062..5d6c01c 100644 (file)
@@ -76,6 +76,7 @@ public:
     void setCurrentItem(HistoryItem*);
     void setCurrentItemTitle(const StringWithDirection&);
     bool currentItemShouldBeReplaced() const;
+    void replaceCurrentItem(HistoryItem*);
 
     HistoryItem* previousItem() const { return m_previousItem.get(); }
 
index ce23278..7d85f39 100644 (file)
 
 namespace WebCore {
 
-class PlaceholderDocument FINAL : public Document {
+class PlaceholderDocument : public Document {
 public:
     static PassRefPtr<PlaceholderDocument> create(Frame* frame, const URL& url)
     {
         return adoptRef(new PlaceholderDocument(frame, url));
     }
 
-private:
-    virtual void createRenderTree() OVERRIDE;
-
+protected:
     PlaceholderDocument(Frame* frame, const URL& url)
         : Document(frame, url)
     {
     }
+
+private:
+    virtual void createRenderTree() OVERRIDE;
 };
 
 } // namespace WebCore
index 1ee8302..8ead413 100644 (file)
 #include "HTMLFrameOwnerElement.h"
 #include "SecurityOrigin.h"
 
+#if USE(QUICK_LOOK)
+#include "QuickLook.h"
+#endif
+
+#if USE(CONTENT_FILTERING)
+#include "ContentFilter.h"
+#endif
+
 namespace WebCore {
 
 PolicyChecker::PolicyChecker(Frame& frame)
@@ -93,6 +101,23 @@ void PolicyChecker::checkNavigationPolicy(const ResourceRequest& request, Docume
 
     m_callback.set(request, formState.get(), std::move(function));
 
+#if USE(QUICK_LOOK)
+    // Always allow QuickLook-generated URLs based on the protocol scheme.
+    if (!request.isNull() && request.url().protocolIs(QLPreviewProtocol())) {
+        continueAfterNavigationPolicy(PolicyUse);
+        return;
+    }
+#endif
+
+#if USE(CONTENT_FILTERING)
+    if (DocumentLoader* documentLoader = m_frame.loader().documentLoader()) {
+        if (documentLoader->handleContentFilterRequest(request)) {
+            continueAfterNavigationPolicy(PolicyIgnore);
+            return;
+        }
+    }
+#endif
+
     m_delegateIsDecidingNavigationPolicy = true;
     m_frame.loader().client().dispatchDecidePolicyForNavigationAction(action, request, formState, [this](PolicyAction action) {
         continueAfterNavigationPolicy(action);
index b0a3edf..06e3879 100644 (file)
@@ -112,6 +112,14 @@ bool ResourceBuffer::hasPurgeableBuffer() const
     return m_sharedBuffer->hasPurgeableBuffer();
 }
 
+#if PLATFORM(IOS)
+void ResourceBuffer::setShouldUsePurgeableMemory(bool shouldUsePurgeableMemory)
+{
+    ASSERT(m_sharedBuffer);
+    sharedBuffer()->shouldUsePurgeableMemory(shouldUsePurgeableMemory);
+}
+#endif
+
 void ResourceBuffer::createPurgeableBuffer() const
 {
     ASSERT(m_sharedBuffer);
index 5dc2d95..5e915b7 100644 (file)
@@ -71,7 +71,12 @@ public:
 
     bool hasPurgeableBuffer() const;
     void createPurgeableBuffer() const;
-    
+
+#if PLATFORM(IOS)
+    // FIXME: Remove PLATFORM(IOS)-guard once we upstream the iOS changes to SharedBuffer.{cpp, h} and SharedBufferCF.cpp.
+    void setShouldUsePurgeableMemory(bool);
+#endif
+
     // Ensure this buffer has no other clients before calling this.
     PassOwnPtr<PurgeableBuffer> releasePurgeableBuffer();
 
index 8368be0..1f8e015 100644 (file)
 #include "ProgressTracker.h"
 #include "ResourceLoader.h"
 
+#if USE(QUICK_LOOK)
+#include "QuickLook.h"
+#endif
+
 namespace WebCore {
 
 ResourceLoadNotifier::ResourceLoadNotifier(Frame& frame)
@@ -107,6 +111,12 @@ void ResourceLoadNotifier::assignIdentifierToInitialRequest(unsigned long identi
 
 void ResourceLoadNotifier::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
 {
+#if USE(QUICK_LOOK)
+    // Always allow QuickLook-generated URLs based on the protocol scheme.
+    if (!request.isNull() && request.url().protocolIs(QLPreviewProtocol()))
+        return;
+#endif
+
     String oldRequestURL = request.url().string();
     m_frame.loader().documentLoader()->didTellClientAboutLoad(request.url());
 
index a8d218d..f59d311 100644 (file)
 #include <wtf/TemporaryChange.h>
 #include <wtf/text/CString.h>
 
+#if PLATFORM(IOS)
+#include <RuntimeApplicationChecksIOS.h>
+#endif
+
 namespace WebCore {
 
-static const unsigned maxRequestsInFlightForNonHTTPProtocols = 20;
 // Match the parallel connection count used by the networking layer.
 static unsigned maxRequestsInFlightPerHost;
+#if !PLATFORM(IOS)
+static const unsigned maxRequestsInFlightForNonHTTPProtocols = 20;
+#else
+// Limiting this seems to regress performance in some local cases so let's just make it large.
+static const unsigned maxRequestsInFlightForNonHTTPProtocols = 10000;
+#endif
 
 ResourceLoadScheduler::HostInformation* ResourceLoadScheduler::hostForURL(const URL& url, CreateHostPolicy createHostPolicy)
 {
@@ -104,6 +113,15 @@ PassRefPtr<SubresourceLoader> ResourceLoadScheduler::scheduleSubresourceLoad(Fra
     RefPtr<SubresourceLoader> loader = SubresourceLoader::create(frame, resource, request, options);
     if (loader)
         scheduleLoad(loader.get(), priority);
+#if PLATFORM(IOS)
+    // Since we defer loader initialization until scheduling on iOS, the frame
+    // load delegate that would be called in SubresourceLoader::create() on
+    // other ports might be called in scheduleLoad() instead. Our contract to
+    // callers of this method is that a null loader is returned if the load was
+    // cancelled by a frame load delegate.
+    if (!loader || loader->reachedTerminalState())
+        return nullptr;
+#endif
     return loader.release();
 }
 
@@ -122,21 +140,49 @@ void ResourceLoadScheduler::scheduleLoad(ResourceLoader* resourceLoader, Resourc
 
     LOG(ResourceLoading, "ResourceLoadScheduler::load resource %p '%s'", resourceLoader, resourceLoader->url().string().latin1().data());
 
+#if PLATFORM(IOS)
     // If there's a web archive resource for this URL, we don't need to schedule the load since it will never touch the network.
+    if (!isSuspendingPendingRequests() && resourceLoader->documentLoader()->archiveResourceForURL(resourceLoader->iOSOriginalRequest().url())) {
+        resourceLoader->startLoading();
+        return;
+    }
+#else
     if (resourceLoader->documentLoader()->archiveResourceForURL(resourceLoader->request().url())) {
         resourceLoader->start();
         return;
     }
+#endif
+
+#if PLATFORM(IOS)
+    HostInformation* host = hostForURL(resourceLoader->iOSOriginalRequest().url(), CreateIfNotFound);
+#else
+    HostInformation* host = hostForURL(resourceLoader->url(), CreateIfNotFound);
+#endif
 
-    HostInformation* host = hostForURL(resourceLoader->url(), CreateIfNotFound);    
     bool hadRequests = host->hasRequests();
     host->schedule(resourceLoader, priority);
 
+#if PLATFORM(IOS)
+    if (ResourceRequest::httpPipeliningEnabled() && !isSuspendingPendingRequests()) {
+        // Serve all requests at once to keep the pipeline full at the network layer.
+        servePendingRequests(host, ResourceLoadPriorityVeryLow);
+        return;
+    }
+#endif
+
+#if PLATFORM(IOS)
+    if ((priority > ResourceLoadPriorityLow || !resourceLoader->iOSOriginalRequest().url().protocolIsInHTTPFamily() || (priority == ResourceLoadPriorityLow && !hadRequests)) && !isSuspendingPendingRequests()) {
+        // Try to request important resources immediately.
+        servePendingRequests(host, priority);
+        return;
+    }
+#else
     if (priority > ResourceLoadPriorityLow || !resourceLoader->url().protocolIsInHTTPFamily() || (priority == ResourceLoadPriorityLow && !hadRequests)) {
         // Try to request important resources immediately.
         servePendingRequests(host, priority);
         return;
     }
+#endif
 
     notifyDidScheduleResourceRequest(resourceLoader);
 
@@ -157,6 +203,15 @@ void ResourceLoadScheduler::remove(ResourceLoader* resourceLoader)
     HostInformation* host = hostForURL(resourceLoader->url());
     if (host)
         host->remove(resourceLoader);
+#if PLATFORM(IOS)
+    // ResourceLoader::url() doesn't start returning the correct value until the load starts. If we get canceled before that, we need to look for originalRequest url instead.
+    // FIXME: ResourceLoader::url() should be made to return a sensible value at all times.
+    if (!resourceLoader->iOSOriginalRequest().isNull()) {
+        HostInformation* originalHost = hostForURL(resourceLoader->iOSOriginalRequest().url());
+        if (originalHost && originalHost != host)
+            originalHost->remove(resourceLoader);
+    }
+#endif
     scheduleServePendingRequests();
 }
 
@@ -164,11 +219,14 @@ void ResourceLoadScheduler::crossOriginRedirectReceived(ResourceLoader* resource
 {
     HostInformation* oldHost = hostForURL(resourceLoader->url());
     ASSERT(oldHost);
+    if (!oldHost)
+        return;
+
     HostInformation* newHost = hostForURL(redirectURL, CreateIfNotFound);
 
     if (oldHost->name() == newHost->name())
         return;
-    
+
     newHost->addLoadInProgress(resourceLoader);
     oldHost->remove(resourceLoader);
 }
@@ -219,6 +277,12 @@ void ResourceLoadScheduler::servePendingRequests(HostInformation* host, Resource
 
             requestsPending.removeFirst();
             host->addLoadInProgress(resourceLoader.get());
+#if PLATFORM(IOS)
+            if (!applicationIsWebProcess()) {
+                resourceLoader->startLoading();
+                return;
+            }
+#endif
             resourceLoader->start();
         }
     }
index f628d49..ddd25b7 100644 (file)
@@ -110,6 +110,15 @@ bool ResourceLoader::init(const ResourceRequest& r)
     ASSERT(!m_documentLoader->isSubstituteLoadPending(this));
     
     ResourceRequest clientRequest(r);
+
+#if PLATFORM(IOS)
+    // If the documentLoader was detached while this ResourceLoader was waiting its turn
+    // in ResourceLoadScheduler queue, don't continue.
+    if (!m_documentLoader->frame()) {
+        cancel();
+        return false;
+    }
+#endif
     
     m_defersLoading = m_frame->page()->defersLoading();
     if (m_options.securityCheck == DoSecurityCheck && !m_frame->document()->securityOrigin()->canDisplay(clientRequest.url())) {
@@ -129,6 +138,13 @@ bool ResourceLoader::init(const ResourceRequest& r)
     }
 
     willSendRequest(clientRequest, ResourceResponse());
+
+#if PLATFORM(IOS)
+    // If this ResourceLoader was stopped as a result of willSendRequest, bail out.
+    if (m_reachedTerminalState)
+        return false;
+#endif
+
     if (clientRequest.isNull()) {
         cancel();
         return false;
@@ -228,6 +244,20 @@ void ResourceLoader::willSendRequest(ResourceRequest& request, const ResourceRes
     Ref<ResourceLoader> protect(*this);
 
     ASSERT(!m_reachedTerminalState);
+    
+#if PLATFORM(IOS)
+    // Ensure an identifier is always set. This ensures that this assetion is not hit:
+    // <rdar://problem/11059794> ASSERTION FAILED: !HashTranslator::equal(KeyTraits::emptyValue(), key) in WebFrameLoaderClient::canAuthenticateAgainstProtectionSpace loading the attached web archive
+    // This is not needed in WebKit2, as it doesn't use m_identifier in WebFrameLoaderClient::canAuthenticateAgainstProtectionSpace
+    if (!m_identifier) {
+        m_identifier = m_frame->page()->progress().createUniqueIdentifier();
+        frameLoader()->notifier().assignIdentifierToInitialRequest(m_identifier, documentLoader(), request);
+
+        // If this ResourceLoader was stopped as a result of assignIdentifierToInitialRequest, bail out
+        if (m_reachedTerminalState)
+            return;
+    }
+#endif
 
     // We need a resource identifier for all requests, even if FrameLoader is never going to see it (such as with CORS preflight requests).
     bool createdResourceIdentifier = false;
@@ -552,6 +582,13 @@ bool ResourceLoader::canAuthenticateAgainstProtectionSpace(const ProtectionSpace
     return frameLoader()->client().canAuthenticateAgainstProtectionSpace(documentLoader(), identifier(), protectionSpace);
 }
 #endif
+    
+#if PLATFORM(IOS)
+RetainPtr<CFDictionaryRef> ResourceLoader::connectionProperties(ResourceHandle*)
+{
+    return frameLoader()->connectionProperties(this);
+}
+#endif
 
 void ResourceLoader::receivedCancellation(const AuthenticationChallenge&)
 {
index a523a7c..6dd9eb6 100644 (file)
@@ -56,6 +56,17 @@ public:
 
     virtual bool init(const ResourceRequest&);
 
+#if PLATFORM(IOS)
+    virtual bool startLoading()
+    {
+        start();
+        return true;
+    }
+
+    virtual const ResourceRequest& iOSOriginalRequest() const { return request(); }
+    virtual RetainPtr<CFDictionaryRef> connectionProperties(ResourceHandle*) OVERRIDE;
+#endif
+
     FrameLoader* frameLoader() const;
     DocumentLoader* documentLoader() const { return m_documentLoader.get(); }
     const ResourceRequest& originalRequest() const { return m_originalRequest; }
index 3ecfc8e..b06f70d 100644 (file)
@@ -432,6 +432,13 @@ bool SubframeLoader::loadPlugin(HTMLPlugInImageElement& pluginElement, const URL
 
     IntSize contentSize = roundedIntSize(LayoutSize(renderer->contentWidth(), renderer->contentHeight()));
     bool loadManually = document()->isPluginDocument() && !m_containsPlugins && toPluginDocument(document())->shouldLoadPluginManually();
+
+#if PLATFORM(IOS)
+    // On iOS, we only tell the plugin to be in full page mode if the containing plugin document is the top level document.
+    if (document()->ownerElement())
+        loadManually = false;
+#endif
+
     RefPtr<Widget> widget = m_frame.loader().client().createPlugin(contentSize, &pluginElement, url, paramNames, paramValues, mimeType, loadManually);
 
     if (!widget) {
index 185b89e..d15d613 100644 (file)
 #include <wtf/StdLibExtras.h>
 #include <wtf/text/CString.h>
 
+#if PLATFORM(IOS)
+#include <RuntimeApplicationChecksIOS.h>
+#endif
+
 namespace WebCore {
 
 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, subresourceLoaderCounter, ("SubresourceLoader"));
@@ -84,10 +88,31 @@ SubresourceLoader::~SubresourceLoader()
 PassRefPtr<SubresourceLoader> SubresourceLoader::create(Frame* frame, CachedResource* resource, const ResourceRequest& request, const ResourceLoaderOptions& options)
 {
     RefPtr<SubresourceLoader> subloader(adoptRef(new SubresourceLoader(frame, resource, options)));
+#if PLATFORM(IOS)
+    if (!applicationIsWebProcess()) {
+        // On iOS, do not invoke synchronous resource load delegates while resource load scheduling
+        // is disabled to avoid re-entering style selection from a different thread (see <rdar://problem/9121719>).
+        // FIXME: This should be fixed for all ports in <https://bugs.webkit.org/show_bug.cgi?id=56647>.
+        subloader->m_iOSOriginalRequest = request;
+        return subloader.release();
+    }
+#endif
     if (!subloader->init(request))
-        return 0;
+        return nullptr;
     return subloader.release();
 }
+    
+#if PLATFORM(IOS)
+bool SubresourceLoader::startLoading()
+{
+    ASSERT(!applicationIsWebProcess());
+    if (!init(m_iOSOriginalRequest))
+        return false;
+    m_iOSOriginalRequest = ResourceRequest();
+    start();
+    return true;
+}
+#endif
 
 CachedResource* SubresourceLoader::cachedResource()
 {
@@ -273,6 +298,11 @@ void SubresourceLoader::didFinishLoading(double finishTime)
     LOG(ResourceLoading, "Received '%s'.", m_resource->url().string().latin1().data());
 
     Ref<SubresourceLoader> protect(*this);
+
+#if PLATFORM(IOS)
+    if (resourceData())
+        resourceData()->setShouldUsePurgeableMemory(true);
+#endif
     CachedResourceHandle<CachedResource> protectResource(m_resource);
     m_state = Finishing;
     m_resource->setLoadFinishTime(finishTime);
@@ -314,13 +344,24 @@ void SubresourceLoader::didFail(const ResourceError& error)
 
 void SubresourceLoader::willCancel(const ResourceError& error)
 {
+#if PLATFORM(IOS)
+    // Since we defer initialization to scheduling time on iOS but
+    // CachedResourceLoader stores resources in the memory cache immediately,
+    // m_resource might be cached despite its loader not being initialized.
+    if (m_state != Initialized && m_state != Uninitialized)
+#else
     if (m_state != Initialized)
+#endif
         return;
     ASSERT(!reachedTerminalState());
     LOG(ResourceLoading, "Cancelled load of '%s'.\n", m_resource->url().string().latin1().data());
 
     Ref<SubresourceLoader> protect(*this);
+#if PLATFORM(IOS)
+    m_state = m_state == Uninitialized ? CancelledWhileInitializing : Finishing;
+#else
     m_state = Finishing;
+#endif
     if (m_resource->resourceToRevalidate())
         memoryCache()->revalidationFailed(m_resource);
     m_resource->setResourceError(error);
@@ -342,7 +383,11 @@ void SubresourceLoader::notifyDone()
         return;
 
     m_requestCountTracker.clear();
+#if PLATFORM(IOS)
+    m_documentLoader->cachedResourceLoader().loadDone(m_resource, m_state != CancelledWhileInitializing);
+#else
     m_documentLoader->cachedResourceLoader().loadDone(m_resource);
+#endif
     if (reachedTerminalState())
         return;
     m_documentLoader->removeSubresourceLoader(this);
@@ -351,7 +396,11 @@ void SubresourceLoader::notifyDone()
 void SubresourceLoader::releaseResources()
 {
     ASSERT(!reachedTerminalState());
+#if PLATFORM(IOS)
+    if (m_state != Uninitialized && m_state != CancelledWhileInitializing)
+#else
     if (m_state != Uninitialized)
+#endif
         m_resource->clearLoader();
     m_resource = 0;
     ResourceLoader::releaseResources();
index 00ab980..ed92f1c 100644 (file)
@@ -52,6 +52,13 @@ public:
     virtual bool isSubresourceLoader() OVERRIDE;
     CachedResource* cachedResource();
 
+#if PLATFORM(IOS)
+    virtual bool startLoading() OVERRIDE;
+
+    // FIXME: What is an "iOS" original request? Why is it necessary?
+    virtual const ResourceRequest& iOSOriginalRequest() const OVERRIDE { return m_iOSOriginalRequest; }
+#endif
+
 private:
     SubresourceLoader(Frame*, CachedResource*, const ResourceLoaderOptions&);
 
@@ -86,7 +93,10 @@ private:
     enum SubresourceLoaderState {
         Uninitialized,
         Initialized,
-        Finishing
+        Finishing,
+#if PLATFORM(IOS)
+        CancelledWhileInitializing
+#endif
     };
 
     class RequestCountTracker {
@@ -98,6 +108,9 @@ private:
         CachedResource* m_resource;
     };
 
+#if PLATFORM(IOS)
+    ResourceRequest m_iOSOriginalRequest;
+#endif
     CachedResource* m_resource;
     bool m_loadingMultipartContent;
     SubresourceLoaderState m_state;
index a74bf2d..cf915a4 100644 (file)
 #include <wtf/StringExtras.h>
 #include <wtf/text/StringBuilder.h>
 
+#if PLATFORM(IOS)
+#include "SQLiteDatabaseTracker.h"
+#endif
+
 namespace WebCore {
 
 static const char flatFileSubdirectory[] = "ApplicationCache";
@@ -100,6 +104,10 @@ static unsigned urlHostHash(const URL& url)
 
 ApplicationCacheGroup* ApplicationCacheStorage::loadCacheGroup(const URL& manifestURL)
 {
+#if PLATFORM(IOS)
+    // FIXME: Move the PLATFORM(IOS)-guards inside the constructor and destructor of SQLiteTransactionInProgressAutoCounter.
+    SQLiteTransactionInProgressAutoCounter transactionCounter;
+#endif
     openDatabase(false);
     if (!m_database.isOpen())
         return 0;
@@ -174,6 +182,10 @@ void ApplicationCacheStorage::loadManifestHostHashes()
     // to avoid trying to open the database over and over if it doesn't exist.
     hasLoadedHashes = true;
     
+#if PLATFORM(IOS)
+    // FIXME: Move the PLATFORM(IOS)-guards inside the constructor and destructor of SQLiteTransactionInProgressAutoCounter.
+    SQLiteTransactionInProgressAutoCounter transactionCounter;
+#endif
     openDatabase(false);
     if (!m_database.isOpen())
         return;
@@ -220,6 +232,11 @@ ApplicationCacheGroup* ApplicationCacheStorage::cacheGroupForURL(const URL& url)
     if (!m_database.isOpen())
         return 0;
         
+#if PLATFORM(IOS)
+    // FIXME: Move the PLATFORM(IOS)-guards inside the constructor and destructor of SQLiteTransactionInProgressAutoCounter.
+    SQLiteTransactionInProgressAutoCounter transactionCounter;
+#endif
+
     // Check the database. Look for all cache groups with a newest cache.
     SQLiteStatement statement(m_database, "SELECT id, manifestURL, newestCache FROM CacheGroups WHERE newestCache IS NOT NULL");
     if (statement.prepare() != SQLResultOk)
@@ -266,6 +283,10 @@ ApplicationCacheGroup* ApplicationCacheStorage::cacheGroupForURL(const URL& url)
 
 ApplicationCacheGroup* ApplicationCacheStorage::fallbackCacheGroupForURL(const URL& url)
 {
+#if PLATFORM(IOS)
+    // FIXME: Move the PLATFORM(IOS)-guards inside the constructor and destructor of SQLiteTransactionInProgressAutoCounter.
+    SQLiteTransactionInProgressAutoCounter transactionCounter;
+#endif
     ASSERT(!url.hasFragmentIdentifier());
 
     // Check if an appropriate cache already exists in memory.
@@ -437,6 +458,10 @@ void ApplicationCacheStorage::setDefaultOriginQuota(int64_t quota)
 
 bool ApplicationCacheStorage::calculateQuotaForOrigin(const SecurityOrigin* origin, int64_t& quota)
 {
+#if PLATFORM(IOS)
+    // FIXME: Move the PLATFORM(IOS)-guards inside the constructor and destructor of SQLiteTransactionInProgressAutoCounter.
+    SQLiteTransactionInProgressAutoCounter transactionCounter;
+#endif
     // If an Origin record doesn't exist, then the COUNT will be 0 and quota will be 0.
     // Using the count to determine if a record existed or not is a safe way to determine
     // if a quota of 0 is real, from the record, or from null.
@@ -460,6 +485,10 @@ bool ApplicationCacheStorage::calculateQuotaForOrigin(const SecurityOrigin* orig
 
 bool ApplicationCacheStorage::calculateUsageForOrigin(const SecurityOrigin* origin, int64_t& usage)
 {
+#if PLATFORM(IOS)
+    // FIXME: Move the PLATFORM(IOS)-guards inside the constructor and destructor of SQLiteTransactionInProgressAutoCounter.
+    SQLiteTransactionInProgressAutoCounter transactionCounter;
+#endif
     // If an Origins record doesn't exist, then the SUM will be null,
     // which will become 0, as expected, when converting to a number.
     SQLiteStatement statement(m_database, "SELECT SUM(Caches.size)"
@@ -484,6 +513,10 @@ bool ApplicationCacheStorage::calculateUsageForOrigin(const SecurityOrigin* orig
 
 bool ApplicationCacheStorage::calculateRemainingSizeForOriginExcludingCache(const SecurityOrigin* origin, ApplicationCache* cache, int64_t& remainingSize)
 {
+#if PLATFORM(IOS)
+    // FIXME: Move the PLATFORM(IOS)-guards inside the constructor and destructor of SQLiteTransactionInProgressAutoCounter.
+    SQLiteTransactionInProgressAutoCounter transactionCounter;
+#endif
     openDatabase(false);
     if (!m_database.isOpen())
         return false;
@@ -533,6 +566,10 @@ bool ApplicationCacheStorage::calculateRemainingSizeForOriginExcludingCache(cons
 
 bool ApplicationCacheStorage::storeUpdatedQuotaForOrigin(const SecurityOrigin* origin, int64_t quota)
 {
+#if PLATFORM(IOS)
+    // FIXME: Move the PLATFORM(IOS)-guards inside the constructor and destructor of SQLiteTransactionInProgressAutoCounter.
+    SQLiteTransactionInProgressAutoCounter transactionCounter;
+#endif
     openDatabase(true);
     if (!m_database.isOpen())
         return false;
@@ -552,6 +589,9 @@ bool ApplicationCacheStorage::storeUpdatedQuotaForOrigin(const SecurityOrigin* o
 
 bool ApplicationCacheStorage::executeSQLCommand(const String& sql)
 {
+#if PLATFORM(IOS)
+    ASSERT(SQLiteDatabaseTracker::hasTransactionInProgress());
+#endif
     ASSERT(m_database.isOpen());
     
     bool result = m_database.executeCommand(sql);
@@ -569,6 +609,9 @@ static const int schemaVersion = 7;
     
 void ApplicationCacheStorage::verifySchemaVersion()
 {
+#if PLATFORM(IOS)
+    ASSERT(SQLiteDatabaseTracker::hasTransactionInProgress());
+#endif
     int version = SQLiteStatement(m_database, "PRAGMA user_version").getColumnInt(0);
     if (version == schemaVersion)
         return;
@@ -593,6 +636,10 @@ void ApplicationCacheStorage::verifySchemaVersion()
     
 void ApplicationCacheStorage::openDatabase(bool createIfDoesNotExist)
 {
+#if PLATFORM(IOS)
+    // FIXME: Move the PLATFORM(IOS)-guards inside the constructor and destructor of SQLiteTransactionInProgressAutoCounter.
+    SQLiteTransactionInProgressAutoCounter transactionCounter;
+#endif
     if (m_database.isOpen())
         return;
 
@@ -660,6 +707,9 @@ void ApplicationCacheStorage::openDatabase(bool createIfDoesNotExist)
 
 bool ApplicationCacheStorage::executeStatement(SQLiteStatement& statement)
 {
+#if PLATFORM(IOS)
+    ASSERT(SQLiteDatabaseTracker::hasTransactionInProgress());
+#endif
     bool result = statement.executeCommand();
     if (!result)
         LOG_ERROR("Application Cache Storage: failed to execute statement \"%s\" error \"%s\"", 
@@ -670,6 +720,9 @@ bool ApplicationCacheStorage::executeStatement(SQLiteStatement& statement)
 
 bool ApplicationCacheStorage::store(ApplicationCacheGroup* group, GroupStorageIDJournal* journal)
 {
+#if PLATFORM(IOS)
+    ASSERT(SQLiteDatabaseTracker::hasTransactionInProgress());
+#endif
     ASSERT(group->storageID() == 0);
     ASSERT(journal);
 
@@ -696,6 +749,9 @@ bool ApplicationCacheStorage::store(ApplicationCacheGroup* group, GroupStorageID
 
 bool ApplicationCacheStorage::store(ApplicationCache* cache, ResourceStorageIDJournal* storageIDJournal)
 {
+#if PLATFORM(IOS)
+    ASSERT(SQLiteDatabaseTracker::hasTransactionInProgress());
+#endif
     ASSERT(cache->storageID() == 0);
     ASSERT(cache->group()->storageID() != 0);
     ASSERT(storageIDJournal);
@@ -777,6 +833,9 @@ bool ApplicationCacheStorage::store(ApplicationCache* cache, ResourceStorageIDJo
 
 bool ApplicationCacheStorage::store(ApplicationCacheResource* resource, unsigned cacheStorageID)
 {
+#if PLATFORM(IOS)
+    ASSERT(SQLiteDatabaseTracker::hasTransactionInProgress());
+#endif
     ASSERT(cacheStorageID);
     ASSERT(!resource->storageID());
     
@@ -894,6 +953,10 @@ bool ApplicationCacheStorage::store(ApplicationCacheResource* resource, unsigned
 
 bool ApplicationCacheStorage::storeUpdatedType(ApplicationCacheResource* resource, ApplicationCache* cache)
 {
+#if PLATFORM(IOS)
+    // FIXME: Move the PLATFORM(IOS)-guards inside the constructor and destructor of SQLiteTransactionInProgressAutoCounter.
+    SQLiteTransactionInProgressAutoCounter transactionCounter;
+#endif
     ASSERT_UNUSED(cache, cache->storageID());
     ASSERT(resource->storageID());
 
@@ -910,6 +973,10 @@ bool ApplicationCacheStorage::storeUpdatedType(ApplicationCacheResource* resourc
 
 bool ApplicationCacheStorage::store(ApplicationCacheResource* resource, ApplicationCache* cache)
 {
+#if PLATFORM(IOS)
+    // FIXME: Move the PLATFORM(IOS)-guards inside the constructor and destructor of SQLiteTransactionInProgressAutoCounter.
+    SQLiteTransactionInProgressAutoCounter transactionCounter;
+#endif
     ASSERT(cache->storageID());
     
     openDatabase(true);
@@ -945,6 +1012,9 @@ bool ApplicationCacheStorage::store(ApplicationCacheResource* resource, Applicat
 
 bool ApplicationCacheStorage::ensureOriginRecord(const SecurityOrigin* origin)
 {
+#if PLATFORM(IOS)
+    ASSERT(SQLiteDatabaseTracker::hasTransactionInProgress());
+#endif
     SQLiteStatement insertOriginStatement(m_database, "INSERT INTO Origins (origin, quota) VALUES (?, ?)");
     if (insertOriginStatement.prepare() != SQLResultOk)
         return false;
@@ -1092,6 +1162,9 @@ static inline void parseHeaders(const String& headers, ResourceResponse& respons
     
 PassRefPtr<ApplicationCache> ApplicationCacheStorage::loadCache(unsigned storageID)
 {
+#if PLATFORM(IOS)
+    ASSERT(SQLiteDatabaseTracker::hasTransactionInProgress());
+#endif
     SQLiteStatement cacheStatement(m_database, 
                                    "SELECT url, statusCode, type, mimeType, textEncodingName, headers, CacheResourceData.data, CacheResourceData.path FROM CacheEntries INNER JOIN CacheResources ON CacheEntries.resource=CacheResources.id "
                                    "INNER JOIN CacheResourceData ON CacheResourceData.id=CacheResources.data WHERE CacheEntries.cache=?");
@@ -1200,6 +1273,10 @@ PassRefPtr<ApplicationCache> ApplicationCacheStorage::loadCache(unsigned storage
     
 void ApplicationCacheStorage::remove(ApplicationCache* cache)
 {
+#if PLATFORM(IOS)
+    // FIXME: Move the PLATFORM(IOS)-guards inside the constructor and destructor of SQLiteTransactionInProgressAutoCounter.
+    SQLiteTransactionInProgressAutoCounter transactionCounter;
+#endif
     if (!cache->storageID())
         return;
     
@@ -1237,6 +1314,10 @@ void ApplicationCacheStorage::remove(ApplicationCache* cache)
 
 void ApplicationCacheStorage::empty()
 {
+#if PLATFORM(IOS)
+    // FIXME: Move the PLATFORM(IOS)-guards inside the constructor and destructor of SQLiteTransactionInProgressAutoCounter.
+    SQLiteTransactionInProgressAutoCounter transactionCounter;
+#endif
     openDatabase(false);
     
     if (!m_database.isOpen())
@@ -1301,6 +1382,10 @@ bool ApplicationCacheStorage::writeDataToUniqueFileInDirectory(SharedBuffer* dat
 
 bool ApplicationCacheStorage::storeCopyOfCache(const String& cacheDirectory, ApplicationCacheHost* cacheHost)
 {
+#if PLATFORM(IOS)
+    // FIXME: Move the PLATFORM(IOS)-guards inside the constructor and destructor of SQLiteTransactionInProgressAutoCounter.
+    SQLiteTransactionInProgressAutoCounter transactionCounter;
+#endif
     ApplicationCache* cache = cacheHost->applicationCache();
     if (!cache)
         return true;
@@ -1337,6 +1422,10 @@ bool ApplicationCacheStorage::storeCopyOfCache(const String& cacheDirectory, App
 
 bool ApplicationCacheStorage::manifestURLs(Vector<URL>* urls)
 {
+#if PLATFORM(IOS)
+    // FIXME: Move the PLATFORM(IOS)-guards inside the constructor and destructor of SQLiteTransactionInProgressAutoCounter.
+    SQLiteTransactionInProgressAutoCounter transactionCounter;
+#endif
     ASSERT(urls);
     openDatabase(false);
     if (!m_database.isOpen())
@@ -1355,6 +1444,10 @@ bool ApplicationCacheStorage::manifestURLs(Vector<URL>* urls)
 
 bool ApplicationCacheStorage::cacheGroupSize(const String& manifestURL, int64_t* size)
 {
+#if PLATFORM(IOS)
+    // FIXME: Move the PLATFORM(IOS)-guards inside the constructor and destructor of SQLiteTransactionInProgressAutoCounter.
+    SQLiteTransactionInProgressAutoCounter transactionCounter;
+#endif
     ASSERT(size);
     openDatabase(false);
     if (!m_database.isOpen())
@@ -1381,6 +1474,10 @@ bool ApplicationCacheStorage::cacheGroupSize(const String& manifestURL, int64_t*
 
 bool ApplicationCacheStorage::deleteCacheGroup(const String& manifestURL)
 {
+#if PLATFORM(IOS)
+    // FIXME: Move the PLATFORM(IOS)-guards inside the constructor and destructor of SQLiteTransactionInProgressAutoCounter.
+    SQLiteTransactionInProgressAutoCounter transactionCounter;
+#endif
     SQLiteTransaction deleteTransaction(m_database);
     // Check to see if the group is in memory.
     ApplicationCacheGroup* group = m_cachesInMemory.get(manifestURL);
@@ -1432,6 +1529,10 @@ bool ApplicationCacheStorage::deleteCacheGroup(const String& manifestURL)
 
 void ApplicationCacheStorage::vacuumDatabaseFile()
 {
+#if PLATFORM(IOS)
+    // FIXME: Move the PLATFORM(IOS)-guards inside the constructor and destructor of SQLiteTransactionInProgressAutoCounter.
+    SQLiteTransactionInProgressAutoCounter transactionCounter;
+#endif
     openDatabase(false);
     if (!m_database.isOpen())
         return;
index 7eb1ce7..d080b1f 100644 (file)
 #include <wtf/StdLibExtras.h>
 #include <wtf/Vector.h>
 
+#if PLATFORM(IOS)
+#include "SystemMemory.h"
+#endif
+
 #if USE(CG)
 #include "PDFDocumentImage.h"
 #endif
@@ -76,6 +80,15 @@ CachedImage::CachedImage(Image* image)
     setLoading(false);
 }
 
+CachedImage::CachedImage(const URL& url, Image* image)
+    : CachedResource(ResourceRequest(url), ImageResource)
+    , m_image(image)
+    , m_shouldPaintBrokenImage(true)
+{
+    setStatus(Cached);
+    setLoading(false);
+}
+
 CachedImage::~CachedImage()
 {
     clearImage();
@@ -267,8 +280,17 @@ LayoutSize CachedImage::imageSizeForRenderer(const RenderObject* renderer, float
     }
 #else
     if (m_image->isBitmapImage() && (renderer && renderer->shouldRespectImageOrientation() == RespectImageOrientation))
+#if !PLATFORM(IOS)
         imageSize = toBitmapImage(m_image.get())->sizeRespectingOrientation();
-#endif
+#else
+    {
+        // On iOS, the image may have been subsampled to accommodate our size restrictions. However
+        // we should tell the renderer what the original size was.
+        imageSize = toBitmapImage(m_image.get())->originalSizeRespectingOrientation();
+    } else if (m_image->isBitmapImage())
+        imageSize = toBitmapImage(m_image.get())->originalSize();
+#endif // !PLATFORM(IOS)
+#endif // ENABLE(CSS_IMAGE_ORIENTATION)
 
 #if ENABLE(SVG)
     else if (m_image->isSVGImage() && sizeType == UsedSize) {
@@ -590,4 +612,29 @@ bool CachedImage::isOriginClean(SecurityOrigin* securityOrigin)
     return !securityOrigin->taintsCanvas(response().url());
 }
 
+#if USE(CF)
+// FIXME: We should look to incorporate the functionality of CachedImageManual
+// into CachedImage or find a better place for this class.
+// FIXME: Remove the USE(CF) once we make MemoryCache::addImageToCache() platform-independent.
+CachedImageManual::CachedImageManual(const URL& url, Image* image)
+    : CachedImage(url, image)
+    , m_fakeClient(std::make_unique<CachedImageClient>())
+{
+    // Use the incoming URL in the response field. This ensures that code
+    // using the response directly, such as origin checks for security,
+    // actually see something.
+    m_response.setURL(url);
+}
+
+bool CachedImageManual::mustRevalidateDueToCacheHeaders(CachePolicy) const
+{
+    // Do not revalidate manually cached images. This mechanism is used as a
+    // way to efficiently share an image from the client to content and
+    // the URL for that image may not represent a resource that can be
+    // retrieved by standard means. If the manual caching SPI is used, it is
+    // incumbent on the client to only use valid resources.
+    return false;
+}
+#endif
+
 } // namespace WebCore
index 4640d69..8bb65de 100644 (file)
@@ -45,12 +45,13 @@ class SecurityOrigin;
 
 struct Length;
 
-class CachedImage FINAL : public CachedResource, public ImageObserver {
+class CachedImage : public CachedResource, public ImageObserver {
     friend class MemoryCache;
 
 public:
     CachedImage(const ResourceRequest&);
     CachedImage(Image*);
+    CachedImage(const URL&, Image*);
     virtual ~CachedImage();
 
     Image* image(); // Returns the nullImage() if the image is not available yet.
@@ -79,6 +80,11 @@ public:
     LayoutSize imageSizeForRenderer(const RenderObject*, float multiplier, SizeType = UsedSize); // returns the size of the complete image.
     void computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio);
 
+#if USE(CF)
+    // FIXME: Remove the USE(CF) once we make MemoryCache::addImageToCache() platform-independent.
+    virtual bool isManual() const { return false; }
+#endif
+
     static void resumeAnimatingImagesForLoader(CachedResourceLoader*);
 
 #if ENABLE(DISK_IMAGE_CACHE)
@@ -143,6 +149,22 @@ private:
     bool m_shouldPaintBrokenImage;
 };
 
+#if USE(CF)
+// FIXME: We should look to incorporate the functionality of CachedImageManual
+// into CachedImage or find a better place for this class.
+// FIXME: Remove the USE(CF) once we make MemoryCache::addImageToCache() platform-independent.
+class CachedImageManual : public CachedImage {
+public:
+    CachedImageManual(const URL&, Image*);
+    void addFakeClient() { addClient(m_fakeClient.get()); }
+    void removeFakeClient() { removeClient(m_fakeClient.get()); }
+    virtual bool isManual() const OVERRIDE { return true; }
+    virtual bool mustRevalidateDueToCacheHeaders(CachePolicy) const;
+private:
+    std::unique_ptr<CachedResourceClient> m_fakeClient;
+};
+#endif
+
 }
 
 #endif
index e53bac5..094e732 100644 (file)
 #include <wtf/text/CString.h>
 #include <wtf/Vector.h>
 
+#if USE(QUICK_LOOK)
+#include "QuickLook.h"
+#endif
+
 using namespace WTF;
 
 namespace WebCore {
@@ -306,6 +310,16 @@ void CachedResource::load(CachedResourceLoader* cachedResourceLoader, const Reso
     m_options = options;
     m_loading = true;
 
+#if USE(QUICK_LOOK)
+    if (!m_resourceRequest.isNull() && m_resourceRequest.url().protocolIs(QLPreviewProtocol())) {
+        // When QuickLook is invoked to convert a document, it returns a unique URL in the
+        // NSURLReponse for the main document. To make safeQLURLForDocumentURLAndResourceURL()
+        // work, we need to use the QL URL not the original URL.
+        const URL& documentURL = cachedResourceLoader->frame() ? cachedResourceLoader->frame()->loader().documentLoader()->response().url() : cachedResourceLoader->document()->url();
+        m_resourceRequest.setURL(safeQLURLForDocumentURLAndResourceURL(documentURL, url()));
+    }
+#endif
+
 #if PLATFORM(BLACKBERRY)
     if (m_resourceRequest.targetType() == ResourceRequest::TargetIsUnspecified)
         m_resourceRequest.setTargetType(cachedResourceTypeToTargetType(type()));
index 40719ba..fb4f5b2 100644 (file)
@@ -228,7 +228,9 @@ public:
     void unregisterHandle(CachedResourceHandleBase* h);
     
     bool canUseCacheValidator() const;
-    bool mustRevalidateDueToCacheHeaders(CachePolicy) const;
+
+    virtual bool mustRevalidateDueToCacheHeaders(CachePolicy) const;
+
     bool isCacheValidator() const { return m_resourceToRevalidate; }
     CachedResource* resourceToRevalidate() const { return m_resourceToRevalidate; }
     
index 9f9e457..2089f3f 100644 (file)
@@ -741,7 +741,7 @@ void CachedResourceLoader::removeCachedResource(CachedResource* resource) const
     m_documentResources.remove(resource->url());
 }
 
-void CachedResourceLoader::loadDone(CachedResource* resource)
+void CachedResourceLoader::loadDone(CachedResource* resource, bool shouldPerformPostLoadActions)
 {
     RefPtr<DocumentLoader> protectDocumentLoader(m_documentLoader);
     RefPtr<Document> protectDocument(m_document);
@@ -766,7 +766,9 @@ void CachedResourceLoader::loadDone(CachedResource* resource)
 
     if (frame())
         frame()->loader().loadDone();
-    performPostLoadActions();
+
+    if (shouldPerformPostLoadActions)
+        performPostLoadActions();
 
     if (!m_garbageCollectDocumentResourcesTimer.isActive())
         m_garbageCollectDocumentResourcesTimer.startOneShot(0);
@@ -826,21 +828,20 @@ void CachedResourceLoader::decrementRequestCount(const CachedResource* res)
 
 void CachedResourceLoader::preload(CachedResource::Type type, CachedResourceRequest& request, const String& charset)
 {
-    bool delaySubresourceLoad = true;
-#if PLATFORM(IOS)
-    delaySubresourceLoad = false;
-#endif
-    if (delaySubresourceLoad) {
-        bool hasRendering = m_document->body() && m_document->body()->renderer();
-        bool canBlockParser = type == CachedResource::Script || type == CachedResource::CSSStyleSheet;
-        if (!hasRendering && !canBlockParser) {
-            // Don't preload subresources that can't block the parser before we have something to draw.
-            // This helps prevent preloads from delaying first display when bandwidth is limited.
-            PendingPreload pendingPreload = { type, request, charset };
-            m_pendingPreloads.append(pendingPreload);
-            return;
-        }
+    // We always preload resources on iOS. See <https://bugs.webkit.org/show_bug.cgi?id=91276>.
+    // FIXME: We should consider adding a setting to toggle aggressive preloading behavior as opposed
+    // to making this behavior specific to iOS.
+#if !PLATFORM(IOS)
+    bool hasRendering = m_document->body() && m_document->body()->renderer();
+    bool canBlockParser = type == CachedResource::Script || type == CachedResource::CSSStyleSheet;
+    if (!hasRendering && !canBlockParser) {
+        // Don't preload subresources that can't block the parser before we have something to draw.
+        // This helps prevent preloads from delaying first display when bandwidth is limited.
+        PendingPreload pendingPreload = { type, request, charset };
+        m_pendingPreloads.append(pendingPreload);
+        return;
     }
+#endif
     requestPreload(type, request, charset);
 }
 
@@ -848,6 +849,12 @@ void CachedResourceLoader::checkForPendingPreloads()
 {
     if (m_pendingPreloads.isEmpty() || !m_document->body() || !m_document->body()->renderer())
         return;
+#if PLATFORM(IOS)
+    // We always preload resources on iOS. See <https://bugs.webkit.org/show_bug.cgi?id=91276>.
+    // So, we should never have any pending preloads.
+    // FIXME: We should look to avoid compiling this code entirely when building for iOS.
+    ASSERT_NOT_REACHED();
+#endif
     while (!m_pendingPreloads.isEmpty()) {
         PendingPreload preload = m_pendingPreloads.takeFirst();
         // Don't request preload if the resource already loaded normally (this will result in double load if the page is being reloaded with cached results ignored).
index 19c970a..39a0a25 100644 (file)
@@ -120,7 +120,9 @@ public:
     void clearDocumentLoader() { m_documentLoader = 0; }
 
     void removeCachedResource(CachedResource*) const;
-    void loadDone(CachedResource*);
+
+    void loadDone(CachedResource*, bool shouldPerformPostLoadActions = true);
+
     void garbageCollectDocumentResources();
     
     void incrementRequestCount(const CachedResource*);
index 506f641..7f47f8b 100644 (file)
@@ -23,6 +23,8 @@
 #include "config.h"
 #include "MemoryCache.h"
 
+#include "BitmapImage.h"
+#include "CachedImage.h"
 #include "CachedResource.h"
 #include "CachedResourceHandle.h"
 #include "CrossThreadTask.h"
@@ -210,18 +212,73 @@ unsigned MemoryCache::liveCapacity() const
     return m_capacity - deadCapacity();
 }
 
-void MemoryCache::pruneLiveResources()
+#if USE(CF)
+// FIXME: Remove the USE(CF) once we either make NativeImagePtr a smart pointer on all platforms or
+// remove the usage of CFRetain() in MemoryCache::addImageToCache() so as to make the code platform-independent.
+bool MemoryCache::addImageToCache(NativeImagePtr image, const URL& url, const String& cachePartition)
+{
+    ASSERT(image);
+    removeImageFromCache(url, cachePartition); // Remove cache entry if it already exists.
+
+    RefPtr<BitmapImage> bitmapImage = BitmapImage::create(image, nullptr);
+    if (!bitmapImage)
+        return false;
+
+    CachedImageManual* cachedImage = new CachedImageManual(url, bitmapImage.get());
+    if (!cachedImage)
+        return false;
+
+    // Actual release of the CGImageRef is done in BitmapImage.
+    CFRetain(image);
+    cachedImage->addFakeClient();
+    cachedImage->setDecodedSize(bitmapImage->decodedSize());
+    cachedImage->resourceRequest().setCachePartition(cachePartition);
+    add(cachedImage);
+    return true;
+}
+
+void MemoryCache::removeImageFromCache(const URL& url, const String& cachePartition)
+{
+#if ENABLE(CACHE_PARTITIONING)
+    CachedResource* resource;
+    if (CachedResourceItem* item = m_resources.get(url))
+        resource = item->get(ResourceRequest::partitionName(cachePartition));
+    else
+        resource = nullptr;
+#else
+    UNUSED_PARAM(cachePartition);
+    CachedResource* resource = m_resources.get(url);
+#endif
+    if (!resource)
+        return;
+
+    // A resource exists and is not a manually cached image, so just remove it.
+    if (!resource->isImage() || !static_cast<CachedImage*>(resource)->isManual()) {
+        evict(resource);
+        return;
+    }
+
+    // Removing the last client of a CachedImage turns the resource
+    // into a dead resource which will eventually be evicted when
+    // dead resources are pruned. That might be immediately since
+    // removing the last client triggers a MemoryCache::prune, so the
+    // resource may be deleted after this call.
+    static_cast<CachedImageManual*>(resource)->removeFakeClient();
+}
+#endif
+
+void MemoryCache::pruneLiveResources(bool shouldDestroyDecodedDataForAllLiveResources)
 {
     if (!m_pruneEnabled)
         return;
 
-    unsigned capacity = liveCapacity();
+    unsigned capacity = shouldDestroyDecodedDataForAllLiveResources ? 0 : liveCapacity();
     if (capacity && m_liveSize <= capacity)
         return;
 
     unsigned targetSize = static_cast<unsigned>(capacity * cTargetPrunePercentage); // Cut by a percentage to avoid immediately pruning again.
 
-    pruneLiveResourcesToSize(targetSize);
+    pruneLiveResourcesToSize(targetSize, shouldDestroyDecodedDataForAllLiveResources);
 }
 
 void MemoryCache::pruneLiveResourcesToPercentage(float prunePercentage)
@@ -238,7 +295,7 @@ void MemoryCache::pruneLiveResourcesToPercentage(float prunePercentage)
     pruneLiveResourcesToSize(targetSize);
 }
 
-void MemoryCache::pruneLiveResourcesToSize(unsigned targetSize)
+void MemoryCache::pruneLiveResourcesToSize(unsigned targetSize, bool shouldDestroyDecodedDataForAllLiveResources)
 {
     if (m_inPruneResources)
         return;
@@ -263,7 +320,7 @@ void MemoryCache::pruneLiveResourcesToSize(unsigned targetSize)
         if (current->isLoaded() && current->decodedSize()) {
             // Check to see if the remaining resources are too new to prune.
             double elapsedTime = currentTime - current->m_lastDecodedAccessTime;
-            if (elapsedTime < cMinDelayBeforeLiveDecodedPrune)
+            if (!shouldDestroyDecodedDataForAllLiveResources && elapsedTime < cMinDelayBeforeLiveDecodedPrune)
                 return;
 
             if (current->decodedDataIsPurgeable()) {
index 3f8b616..65f92f9 100644 (file)
@@ -25,6 +25,7 @@
 #ifndef Cache_h
 #define Cache_h
 
+#include "NativeImagePtr.h"
 #include "SecurityOriginHash.h"
 #include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
@@ -187,10 +188,27 @@ public:
     unsigned liveSize() const { return m_liveSize; }
     unsigned deadSize() const { return m_deadSize; }
 
+#if USE(CF)
+    // FIXME: Remove the USE(CF) once we either make NativeImagePtr a smart pointer on all platforms or
+    // remove the usage of CFRetain() in MemoryCache::addImageToCache() so as to make the code platform-independent.
+    bool addImageToCache(NativeImagePtr, const URL&, const String& cachePartition);
+    void removeImageFromCache(const URL&, const String& cachePartition);
+#endif
+
+    // pruneDead*() - Flush decoded and encoded data from resources not referenced by Web pages.
+    // pruneLive*() - Flush decoded data from resources still referenced by Web pages.
+    void pruneDeadResources(); // Automatically decide how much to prune.
+    void pruneLiveResources(bool shouldDestroyDecodedDataForAllLiveResources = false);
+
 private:
+    void pruneDeadResourcesToPercentage(float prunePercentage); // Prune to % current size
+    void pruneLiveResourcesToPercentage(float prunePercentage);
+    void pruneDeadResourcesToSize(unsigned targetSize);
+    void pruneLiveResourcesToSize(unsigned targetSize, bool shouldDestroyDecodedDataForAllLiveResources = false);
+
     MemoryCache();
     ~MemoryCache(); // Not implemented to make sure nobody accidentally calls delete -- WebCore does not delete singletons.
-       
+
     LRUList* lruListFor(CachedResource*);
 #ifndef NDEBUG
     void dumpStats();
@@ -200,15 +218,6 @@ private:
     unsigned liveCapacity() const;
     unsigned deadCapacity() const;
 
-    // pruneDead*() - Flush decoded and encoded data from resources not referenced by Web pages.
-    // pruneLive*() - Flush decoded data from resources still referenced by Web pages.
-    void pruneDeadResources(); // Automatically decide how much to prune.
-    void pruneLiveResources();
-    void pruneDeadResourcesToPercentage(float prunePercentage); // Prune to % current size
-    void pruneLiveResourcesToPercentage(float prunePercentage);
-    void pruneDeadResourcesToSize(unsigned targetSize);
-    void pruneLiveResourcesToSize(unsigned targetSize);
-
     bool makeResourcePurgeable(CachedResource*);
     void evict(CachedResource*);
 
index 29fd9f2..5767604 100644 (file)
@@ -25,6 +25,7 @@
 #include "config.h"
 #include "SubresourceLoader.h"
 
+#include "CachedResource.h"
 #include <wtf/Ref.h>
 
 namespace WebCore {
@@ -32,8 +33,8 @@ namespace WebCore {
 #if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
 void SubresourceLoader::didReceiveDataArray(CFArrayRef dataArray)
 {
-    // Reference the object in this method since the additional processing can do
-    // anything including removing the last reference to this object; one example of this is 3266216.
+    // Reference the object in this method since the additional processing can do anything including
+    // removing the last reference to this object; one example of this is <rdar://problem/3266216>.
     Ref<SubresourceLoader> protect(*this);
 
     ResourceLoader::didReceiveDataArray(dataArray);
@@ -46,8 +47,19 @@ void SubresourceLoader::didReceiveDataArray(CFArrayRef dataArray)
     if (!m_loadingMultipartContent) {
         CFIndex arrayCount = CFArrayGetCount(dataArray);
         for (CFIndex i = 0; i < arrayCount; ++i)  {
-            CFDataRef data = reinterpret_cast<CFDataRef>(CFArrayGetValueAtIndex(dataArray, i));
-            sendDataToResource(reinterpret_cast<const char *>(CFDataGetBytePtr(data)), static_cast<int>(CFDataGetLength(data)));
+            // A previous iteration of this loop might have resulted in the load
+            // being cancelled. Bail out if we no longer have a cached resource.
+            if (!m_resource)
+                return;
+            if (ResourceBuffer* resourceData = this->resourceData())
+                m_resource->addDataBuffer(resourceData);
+            else {
+                CFDataRef cfData = reinterpret_cast<CFDataRef>(CFArrayGetValueAtIndex(dataArray, i));
+                const char* data = reinterpret_cast<const char *>(CFDataGetBytePtr(cfData));
+                CFIndex length = CFDataGetLength(cfData);
+                ASSERT(length <= std::numeric_limits<CFIndex>::max());
+                m_resource->addData(data, static_cast<unsigned>(length));
+            }
         }
     }
 }
index 91dda6e..95af790 100644 (file)
 #include "DocumentLoader.h"
 #include "ResourceHandle.h"
 #include "ResourceLoader.h"
+#include <wtf/SchedulePair.h>
 
 namespace WebCore {
 
+#if !PLATFORM(IOS)
 static void scheduleAll(const ResourceLoaderSet& loaders, SchedulePair* pair)
 {
     const ResourceLoaderSet copy = loaders;
@@ -50,23 +52,32 @@ static void unscheduleAll(const ResourceLoaderSet& loaders, SchedulePair* pair)
         if (ResourceHandle* handle = (*it)->handle())
             handle->unschedule(pair);
 }
+#endif
 
 void DocumentLoader::schedule(SchedulePair* pair)
 {
+#if !PLATFORM(IOS)
     if (mainResourceLoader() && mainResourceLoader()->handle())
         mainResourceLoader()->handle()->schedule(pair);
     scheduleAll(m_subresourceLoaders, pair);
     scheduleAll(m_plugInStreamLoaders, pair);
     scheduleAll(m_multipartSubresourceLoaders, pair);
+#else
+    UNUSED_PARAM(pair);
+#endif
 }
 
 void DocumentLoader::unschedule(SchedulePair* pair)
 {
+#if !PLATFORM(IOS)
     if (mainResourceLoader() && mainResourceLoader()->handle())
         mainResourceLoader()->handle()->unschedule(pair);
     unscheduleAll(m_subresourceLoaders, pair);
     unscheduleAll(m_plugInStreamLoaders, pair);
     unscheduleAll(m_multipartSubresourceLoaders, pair);
+#else
+    UNUSED_PARAM(pair);
+#endif
 }
 
 } // namespace
index f9623ec..e37f795 100644 (file)
@@ -125,6 +125,8 @@ public:
     IntSize currentFrameSize() const;
     virtual bool getHotSpot(IntPoint&) const OVERRIDE;
 
+    unsigned decodedSize() const { return m_decodedSize; }
+
     virtual bool dataChanged(bool allDataReceived) OVERRIDE;
     virtual String filenameExtension() const OVERRIDE;