diff options
Diffstat (limited to 'Source/WebCore/loader')
51 files changed, 1256 insertions, 657 deletions
diff --git a/Source/WebCore/loader/DocumentLoader.cpp b/Source/WebCore/loader/DocumentLoader.cpp index e223765..121045b 100644 --- a/Source/WebCore/loader/DocumentLoader.cpp +++ b/Source/WebCore/loader/DocumentLoader.cpp @@ -112,6 +112,10 @@ FrameLoader* DocumentLoader::frameLoader() const DocumentLoader::~DocumentLoader() { ASSERT(!m_frame || frameLoader()->activeDocumentLoader() != this || !frameLoader()->isLoading()); + if (m_iconLoadDecisionCallback) + m_iconLoadDecisionCallback->invalidate(); + if (m_iconDataCallback) + m_iconDataCallback->invalidate(); } PassRefPtr<SharedBuffer> DocumentLoader::mainResourceData() const @@ -836,7 +840,41 @@ void DocumentLoader::transferLoadingResourcesFromPage(Page* oldPage) void DocumentLoader::iconLoadDecisionAvailable() { if (m_frame) - m_frame->loader()->iconLoadDecisionAvailable(); + m_frame->loader()->iconLoadDecisionReceived(iconDatabase().synchronousLoadDecisionForIconURL(KURL(frameLoader()->iconURL()), this)); } +static void iconLoadDecisionCallback(IconLoadDecision decision, void* context) +{ + static_cast<DocumentLoader*>(context)->continueIconLoadWithDecision(decision); +} + +void DocumentLoader::getIconLoadDecisionForIconURL(const String& urlString) +{ + if (m_iconLoadDecisionCallback) + m_iconLoadDecisionCallback->invalidate(); + m_iconLoadDecisionCallback = IconLoadDecisionCallback::create(this, iconLoadDecisionCallback); + iconDatabase().loadDecisionForIconURL(urlString, m_iconLoadDecisionCallback); +} + +void DocumentLoader::continueIconLoadWithDecision(IconLoadDecision decision) +{ + ASSERT(m_iconLoadDecisionCallback); + m_iconLoadDecisionCallback = 0; + if (m_frame) + m_frame->loader()->continueIconLoadWithDecision(decision); +} + +static void iconDataCallback(SharedBuffer*, void*) +{ + // FIXME: Implement this once we know what parts of WebCore actually need the icon data returned. } + +void DocumentLoader::getIconDataForIconURL(const String& urlString) +{ + if (m_iconDataCallback) + m_iconDataCallback->invalidate(); + m_iconDataCallback = IconDataCallback::create(this, iconDataCallback); + iconDatabase().iconDataForIconURL(urlString, m_iconDataCallback); +} + +} // namespace WebCore diff --git a/Source/WebCore/loader/DocumentLoader.h b/Source/WebCore/loader/DocumentLoader.h index 8e9ab8f..1f88272 100644 --- a/Source/WebCore/loader/DocumentLoader.h +++ b/Source/WebCore/loader/DocumentLoader.h @@ -31,6 +31,7 @@ #include "DocumentLoadTiming.h" #include "DocumentWriter.h" +#include "IconDatabaseBase.h" #include "NavigationAction.h" #include "ResourceError.h" #include "ResourceRequest.h" @@ -182,7 +183,7 @@ namespace WebCore { String clientRedirectDestinationForHistory() const { return urlForHistory(); } void setClientRedirectSourceForHistory(const String& clientedirectSourceForHistory) { m_clientRedirectSourceForHistory = clientedirectSourceForHistory; } - String serverRedirectSourceForHistory() const { return urlForHistory() == url() ? String() : urlForHistory(); } // null if no server redirect occurred. + String serverRedirectSourceForHistory() const { return urlForHistory() == url() ? String() : urlForHistory().string(); } // null if no server redirect occurred. String serverRedirectDestinationForHistory() const { return url(); } bool didCreateGlobalHistoryEntry() const { return m_didCreateGlobalHistoryEntry; } @@ -193,8 +194,14 @@ namespace WebCore { bool startLoadingMainResource(unsigned long identifier); void cancelMainResourceLoad(const ResourceError&); + // Support iconDatabase in synchronous mode. void iconLoadDecisionAvailable(); + // Support iconDatabase in asynchronous mode. + void continueIconLoadWithDecision(IconLoadDecision); + void getIconLoadDecisionForIconURL(const String&); + void getIconDataForIconURL(const String&); + bool isLoadingMainResource() const; bool isLoadingSubresources() const; bool isLoadingPlugIns() const; @@ -326,6 +333,9 @@ namespace WebCore { bool m_didCreateGlobalHistoryEntry; DocumentLoadTiming m_documentLoadTiming; + + RefPtr<IconLoadDecisionCallback> m_iconLoadDecisionCallback; + RefPtr<IconDataCallback> m_iconDataCallback; #if ENABLE(OFFLINE_WEB_APPLICATIONS) friend class ApplicationCacheHost; // for substitute resource delivery diff --git a/Source/WebCore/loader/DocumentThreadableLoader.cpp b/Source/WebCore/loader/DocumentThreadableLoader.cpp index 732a84e..73c3e80 100644 --- a/Source/WebCore/loader/DocumentThreadableLoader.cpp +++ b/Source/WebCore/loader/DocumentThreadableLoader.cpp @@ -51,27 +51,30 @@ namespace WebCore { void DocumentThreadableLoader::loadResourceSynchronously(Document* document, const ResourceRequest& request, ThreadableLoaderClient& client, const ThreadableLoaderOptions& options) { // The loader will be deleted as soon as this function exits. - RefPtr<DocumentThreadableLoader> loader = adoptRef(new DocumentThreadableLoader(document, &client, LoadSynchronously, request, options)); + RefPtr<DocumentThreadableLoader> loader = adoptRef(new DocumentThreadableLoader(document, &client, LoadSynchronously, request, options, String())); ASSERT(loader->hasOneRef()); } -PassRefPtr<DocumentThreadableLoader> DocumentThreadableLoader::create(Document* document, ThreadableLoaderClient* client, const ResourceRequest& request, const ThreadableLoaderOptions& options) +PassRefPtr<DocumentThreadableLoader> DocumentThreadableLoader::create(Document* document, ThreadableLoaderClient* client, const ResourceRequest& request, const ThreadableLoaderOptions& options, const String& optionalOutgoingReferrer) { - RefPtr<DocumentThreadableLoader> loader = adoptRef(new DocumentThreadableLoader(document, client, LoadAsynchronously, request, options)); + RefPtr<DocumentThreadableLoader> loader = adoptRef(new DocumentThreadableLoader(document, client, LoadAsynchronously, request, options, optionalOutgoingReferrer)); if (!loader->m_loader) loader = 0; return loader.release(); } -DocumentThreadableLoader::DocumentThreadableLoader(Document* document, ThreadableLoaderClient* client, BlockingBehavior blockingBehavior, const ResourceRequest& request, const ThreadableLoaderOptions& options) +DocumentThreadableLoader::DocumentThreadableLoader(Document* document, ThreadableLoaderClient* client, BlockingBehavior blockingBehavior, const ResourceRequest& request, const ThreadableLoaderOptions& options, const String& optionalOutgoingReferrer) : m_client(client) , m_document(document) , m_options(options) + , m_optionalOutgoingReferrer(optionalOutgoingReferrer) , m_sameOriginRequest(document->securityOrigin()->canRequest(request.url())) , m_async(blockingBehavior == LoadAsynchronously) { ASSERT(document); ASSERT(client); + // Setting an outgoing referer is only supported in the async code path. + ASSERT(m_async || m_optionalOutgoingReferrer.isEmpty()); if (m_sameOriginRequest || m_options.crossOriginRequestPolicy == AllowCrossOriginRequests) { loadRequest(request, DoSecurityCheck); @@ -346,7 +349,8 @@ void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, Secur // Clear the loader so that any callbacks from SubresourceLoader::create will not have the old loader. m_loader = 0; - m_loader = resourceLoadScheduler()->scheduleSubresourceLoad(m_document->frame(), this, request, ResourceLoadPriorityMedium, securityCheck, sendLoadCallbacks, sniffContent); + m_loader = resourceLoadScheduler()->scheduleSubresourceLoad(m_document->frame(), this, request, ResourceLoadPriorityMedium, securityCheck, sendLoadCallbacks, + sniffContent, m_optionalOutgoingReferrer); return; } diff --git a/Source/WebCore/loader/DocumentThreadableLoader.h b/Source/WebCore/loader/DocumentThreadableLoader.h index 94884ce..c511306 100644 --- a/Source/WebCore/loader/DocumentThreadableLoader.h +++ b/Source/WebCore/loader/DocumentThreadableLoader.h @@ -39,6 +39,7 @@ #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> +#include <wtf/text/WTFString.h> namespace WebCore { class Document; @@ -50,7 +51,7 @@ namespace WebCore { WTF_MAKE_FAST_ALLOCATED; public: static void loadResourceSynchronously(Document*, const ResourceRequest&, ThreadableLoaderClient&, const ThreadableLoaderOptions&); - static PassRefPtr<DocumentThreadableLoader> create(Document*, ThreadableLoaderClient*, const ResourceRequest&, const ThreadableLoaderOptions&); + static PassRefPtr<DocumentThreadableLoader> create(Document*, ThreadableLoaderClient*, const ResourceRequest&, const ThreadableLoaderOptions&, const String& optionalOutgoingReferrer = String()); virtual ~DocumentThreadableLoader(); virtual void cancel(); @@ -69,7 +70,7 @@ namespace WebCore { LoadAsynchronously }; - DocumentThreadableLoader(Document*, ThreadableLoaderClient*, BlockingBehavior blockingBehavior, const ResourceRequest&, const ThreadableLoaderOptions& options); + DocumentThreadableLoader(Document*, ThreadableLoaderClient*, BlockingBehavior, const ResourceRequest&, const ThreadableLoaderOptions&, const String& optionalOutgoingReferrer); virtual void willSendRequest(SubresourceLoader*, ResourceRequest&, const ResourceResponse& redirectResponse); virtual void didSendData(SubresourceLoader*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent); @@ -97,6 +98,7 @@ namespace WebCore { ThreadableLoaderClient* m_client; Document* m_document; ThreadableLoaderOptions m_options; + String m_optionalOutgoingReferrer; bool m_sameOriginRequest; bool m_async; OwnPtr<ResourceRequest> m_actualRequest; // non-null during Access Control preflight checks diff --git a/Source/WebCore/loader/DocumentThreadableLoaderClient.h b/Source/WebCore/loader/DocumentThreadableLoaderClient.h index 4551b84..146a166 100644 --- a/Source/WebCore/loader/DocumentThreadableLoaderClient.h +++ b/Source/WebCore/loader/DocumentThreadableLoaderClient.h @@ -45,6 +45,9 @@ public: virtual bool isDocumentThreadableLoaderClient() { return true; } virtual void willSendRequest(ResourceRequest& /*newRequest*/, const ResourceResponse& /*redirectResponse*/) { } + +protected: + DocumentThreadableLoaderClient() { } }; } // namespace WebCore diff --git a/Source/WebCore/loader/EmptyClients.h b/Source/WebCore/loader/EmptyClients.h index 41a5df7..cabb4ae 100644 --- a/Source/WebCore/loader/EmptyClients.h +++ b/Source/WebCore/loader/EmptyClients.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2006 Eric Seidel (eric@webkit.org) - * Copyright (C) 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Redistribution and use in source and binary forms, with or without @@ -165,7 +165,7 @@ public: virtual void invalidateContentsForSlowScroll(const IntRect&, bool) {}; virtual void scroll(const IntSize&, const IntRect&, const IntRect&) { } #if ENABLE(TILED_BACKING_STORE) - virtual void delegatedScrollRequested(const IntSize&) { } + virtual void delegatedScrollRequested(const IntPoint&) { } #endif #if ENABLE(REQUEST_ANIMATION_FRAME) virtual void scheduleAnimation() { } @@ -374,7 +374,7 @@ public: virtual void showMediaPlayerProxyPlugin(Widget*) { } #endif - virtual ObjectContentType objectContentType(const KURL&, const String&) { return ObjectContentType(); } + virtual ObjectContentType objectContentType(const KURL&, const String&, bool) { return ObjectContentType(); } virtual String overrideMediaType() const { return String(); } virtual void redirectDataToPlugin(Widget*) { } @@ -414,7 +414,7 @@ public: virtual String getAutoCorrectSuggestionForMisspelledWord(const String&) { return String(); } virtual void checkGrammarOfString(const UChar*, int, Vector<GrammarDetail>&, int*, int*) { } -#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) +#if USE(UNIFIED_TEXT_CHECKING) virtual void checkTextOfParagraph(const UChar*, int, uint64_t, Vector<TextCheckingResult>&) { }; #endif @@ -519,9 +519,9 @@ public: TextCheckerClient* textChecker() { return &m_textCheckerClient; } #if SUPPORT_AUTOCORRECTION_PANEL - virtual void showCorrectionPanel(CorrectionPanelInfo::PanelType, const FloatRect&, const String&, const String&, const Vector<String>&, Editor*) { } + virtual void showCorrectionPanel(CorrectionPanelInfo::PanelType, const FloatRect&, const String&, const String&, const Vector<String>&) { } virtual void dismissCorrectionPanel(ReasonForDismissingCorrectionPanel) { } - virtual bool isShowingCorrectionPanel() { return false; } + virtual String dismissCorrectionPanelSoon(ReasonForDismissingCorrectionPanel) { return String(); } virtual void recordAutocorrectionResponse(AutocorrectionResponseType, const String&, const String&) { } #endif virtual void updateSpellingUIWithGrammarString(const String&, const GrammarDetail&) { } diff --git a/Source/WebCore/loader/FrameLoader.cpp b/Source/WebCore/loader/FrameLoader.cpp index 61f421f..6819e71 100644 --- a/Source/WebCore/loader/FrameLoader.cpp +++ b/Source/WebCore/loader/FrameLoader.cpp @@ -1,9 +1,10 @@ /* - * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * Copyright (C) 2008 Alp Toker <alp@atoker.com> * Copyright (C) Research In Motion Limited 2009. All rights reserved. + * Copyright (C) 2011 Kris Jordan <krisjordan@gmail.com> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -40,6 +41,7 @@ #include "CachedPage.h" #include "CachedResourceLoader.h" #include "Chrome.h" +#include "ContentSecurityPolicy.h" #include "DOMImplementation.h" #include "DOMWindow.h" #include "Document.h" @@ -83,6 +85,7 @@ #include "ResourceHandle.h" #include "ResourceRequest.h" #include "SchemeRegistry.h" +#include "ScrollAnimator.h" #include "ScriptController.h" #include "ScriptSourceCode.h" #include "SecurityOrigin.h" @@ -130,9 +133,9 @@ using namespace SVGNames; #endif #if ENABLE(XHTMLMP) -static const char defaultAcceptHeader[] = "application/xml,application/vnd.wap.xhtml+xml,application/xhtml+xml;profile='http://www.wapforum.org/xhtml',text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"; +static const char defaultAcceptHeader[] = "application/vnd.wap.xhtml+xml,application/xhtml+xml;profile='http://www.wapforum.org/xhtml',text/html,application/xml;q=0.9,*/*;q=0.8"; #else -static const char defaultAcceptHeader[] = "application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"; +static const char defaultAcceptHeader[] = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; #endif static double storedTimeOfLastCompletedLoad; @@ -258,13 +261,6 @@ void FrameLoader::setDefersLoading(bool defers) m_frame->navigationScheduler()->startTimer(); startCheckCompleteTimer(); } - - // This code is not logically part of load deferring, but we do not want JS code executed beneath modal - // windows or sheets, which is exactly when PageGroupLoadDeferrer is used. - if (defers) - m_frame->document()->suspendScheduledTasks(); - else - m_frame->document()->resumeScheduledTasks(); } bool FrameLoader::canHandleRequest(const ResourceRequest& request) @@ -691,12 +687,13 @@ void FrameLoader::didEndDocument() m_isLoadingMainResource = false; } -void FrameLoader::iconLoadDecisionAvailable() +// Callback for the old-style synchronous IconDatabase interface. +void FrameLoader::iconLoadDecisionReceived(IconLoadDecision iconLoadDecision) { if (!m_mayLoadIconLater) return; LOG(IconDatabase, "FrameLoader %p was told a load decision is available for its icon", this); - startIconLoader(); + continueIconLoadWithDecision(iconLoadDecision); m_mayLoadIconLater = false; } @@ -715,48 +712,77 @@ void FrameLoader::startIconLoader() if (urlString.isEmpty()) return; - // If we're not reloading and the icon database doesn't say to load now then bail before we actually start the load - if (loadType() != FrameLoadTypeReload && loadType() != FrameLoadTypeReloadFromOrigin) { - IconLoadDecision decision = iconDatabase().loadDecisionForIconURL(urlString, m_documentLoader.get()); - if (decision == IconLoadNo) { - LOG(IconDatabase, "FrameLoader::startIconLoader() - Told not to load this icon, committing iconURL %s to database for pageURL mapping", urlString.ascii().data()); - commitIconURLToIconDatabase(url); - - // We were told not to load this icon - that means this icon is already known by the database - // If the icon data hasn't been read in from disk yet, kick off the read of the icon from the database to make sure someone - // has done it. This is after registering for the notification so the WebView can call the appropriate delegate method. - // Otherwise if the icon data *is* available, notify the delegate - if (!iconDatabase().iconDataKnownForIconURL(urlString)) { - LOG(IconDatabase, "Told not to load icon %s but icon data is not yet available - registering for notification and requesting load from disk", urlString.ascii().data()); - m_client->registerForIconNotification(); - iconDatabase().iconForPageURL(m_frame->document()->url().string(), IntSize(0, 0)); - iconDatabase().iconForPageURL(originalRequestURL().string(), IntSize(0, 0)); - } else - m_client->dispatchDidReceiveIcon(); - - return; - } - - if (decision == IconLoadUnknown) { - // In this case, we may end up loading the icon later, but we still want to commit the icon url mapping to the database - // just in case we don't end up loading later - if we commit the mapping a second time after the load, that's no big deal - // We also tell the client to register for the notification that the icon is received now so it isn't missed in case the - // icon is later read in from disk - LOG(IconDatabase, "FrameLoader %p might load icon %s later", this, urlString.ascii().data()); - m_mayLoadIconLater = true; - m_client->registerForIconNotification(); - commitIconURLToIconDatabase(url); - return; - } - } - // People who want to avoid loading images generally want to avoid loading all images. // Now that we've accounted for URL mapping, avoid starting the network load if images aren't set to display automatically. Settings* settings = m_frame->settings(); if (settings && !settings->loadsImagesAutomatically()) return; - // This is either a reload or the icon database said "yes, load the icon", so kick off the load! + // If we're reloading the page, always start the icon load now. + if (loadType() == FrameLoadTypeReload && loadType() == FrameLoadTypeReloadFromOrigin) { + continueIconLoadWithDecision(IconLoadYes); + return; + } + + if (iconDatabase().supportsAsynchronousMode()) { + m_documentLoader->getIconLoadDecisionForIconURL(urlString); + // Commit the icon url mapping to the database just in case we don't end up loading later. + commitIconURLToIconDatabase(url); + return; + } + + IconLoadDecision decision = iconDatabase().synchronousLoadDecisionForIconURL(urlString, m_documentLoader.get()); + + if (decision == IconLoadUnknown) { + // In this case, we may end up loading the icon later, but we still want to commit the icon url mapping to the database + // just in case we don't end up loading later - if we commit the mapping a second time after the load, that's no big deal + // We also tell the client to register for the notification that the icon is received now so it isn't missed in case the + // icon is later read in from disk + LOG(IconDatabase, "FrameLoader %p might load icon %s later", this, urlString.ascii().data()); + m_mayLoadIconLater = true; + m_client->registerForIconNotification(); + commitIconURLToIconDatabase(url); + return; + } + + continueIconLoadWithDecision(decision); +} + +void FrameLoader::continueIconLoadWithDecision(IconLoadDecision iconLoadDecision) +{ + ASSERT(iconLoadDecision != IconLoadUnknown); + + // FIXME (<rdar://problem/9168605>) - We should support in-memory-only private browsing icons in asynchronous icon database mode. + if (iconDatabase().supportsAsynchronousMode() && m_frame->page()->settings()->privateBrowsingEnabled()) + return; + + if (iconLoadDecision == IconLoadNo) { + KURL url(iconURL()); + String urlString(url.string()); + + LOG(IconDatabase, "FrameLoader::startIconLoader() - Told not to load this icon, committing iconURL %s to database for pageURL mapping", urlString.ascii().data()); + commitIconURLToIconDatabase(url); + + if (iconDatabase().supportsAsynchronousMode()) { + m_documentLoader->getIconDataForIconURL(urlString); + return; + } + + // We were told not to load this icon - that means this icon is already known by the database + // If the icon data hasn't been read in from disk yet, kick off the read of the icon from the database to make sure someone + // has done it. This is after registering for the notification so the WebView can call the appropriate delegate method. + // Otherwise if the icon data *is* available, notify the delegate + if (!iconDatabase().synchronousIconDataKnownForIconURL(urlString)) { + LOG(IconDatabase, "Told not to load icon %s but icon data is not yet available - registering for notification and requesting load from disk", urlString.ascii().data()); + m_client->registerForIconNotification(); + iconDatabase().synchronousIconForPageURL(m_frame->document()->url().string(), IntSize(0, 0)); + iconDatabase().synchronousIconForPageURL(originalRequestURL().string(), IntSize(0, 0)); + } else + m_client->dispatchDidReceiveIcon(); + + return; + } + if (!m_iconLoader) m_iconLoader = IconLoader::create(m_frame); @@ -966,7 +992,7 @@ void FrameLoader::loadArchive(PassRefPtr<Archive> prpArchive) } #endif // ENABLE(WEB_ARCHIVE) -ObjectContentType FrameLoader::defaultObjectContentType(const KURL& url, const String& mimeTypeIn) +ObjectContentType FrameLoader::defaultObjectContentType(const KURL& url, const String& mimeTypeIn, bool shouldPreferPlugInsForImages) { String mimeType = mimeTypeIn; String extension = url.path().substring(url.path().reverseFind('.') + 1); @@ -983,13 +1009,17 @@ ObjectContentType FrameLoader::defaultObjectContentType(const KURL& url, const S if (mimeType.isEmpty()) return ObjectContentFrame; // Go ahead and hope that we can display the content. +#if !PLATFORM(MAC) && !PLATFORM(CHROMIUM) && !PLATFORM(EFL) // Mac has no PluginDatabase, nor does Chromium or EFL + bool plugInSupportsMIMEType = PluginDatabase::installedPlugins()->isMIMETypeRegistered(mimeType); +#else + bool plugInSupportsMIMEType = false; +#endif + if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType)) - return WebCore::ObjectContentImage; + return shouldPreferPlugInsForImages && plugInSupportsMIMEType ? WebCore::ObjectContentNetscapePlugin : WebCore::ObjectContentImage; -#if !PLATFORM(MAC) && !PLATFORM(CHROMIUM) && !PLATFORM(EFL) // Mac has no PluginDatabase, nor does Chromium or EFL - if (PluginDatabase::installedPlugins()->isMIMETypeRegistered(mimeType)) + if (plugInSupportsMIMEType) return WebCore::ObjectContentNetscapePlugin; -#endif if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType)) return WebCore::ObjectContentFrame; @@ -1392,7 +1422,7 @@ void FrameLoader::load(const ResourceRequest& request, const SubstituteData& sub m_loadType = FrameLoadTypeStandard; RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, substituteData); if (lockHistory && m_documentLoader) - loader->setClientRedirectSourceForHistory(m_documentLoader->didCreateGlobalHistoryEntry() ? m_documentLoader->urlForHistory() : m_documentLoader->clientRedirectSourceForHistory()); + loader->setClientRedirectSourceForHistory(m_documentLoader->didCreateGlobalHistoryEntry() ? m_documentLoader->urlForHistory().string() : m_documentLoader->clientRedirectSourceForHistory()); load(loader.get()); } @@ -1416,7 +1446,7 @@ void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, const { RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, SubstituteData()); if (lockHistory && m_documentLoader) - loader->setClientRedirectSourceForHistory(m_documentLoader->didCreateGlobalHistoryEntry() ? m_documentLoader->urlForHistory() : m_documentLoader->clientRedirectSourceForHistory()); + loader->setClientRedirectSourceForHistory(m_documentLoader->didCreateGlobalHistoryEntry() ? m_documentLoader->urlForHistory().string() : m_documentLoader->clientRedirectSourceForHistory()); loader->setTriggeringAction(action); if (m_documentLoader) @@ -1530,7 +1560,7 @@ bool FrameLoader::willLoadMediaElementURL(KURL& url) unsigned long identifier; ResourceError error; requestFromDelegate(request, identifier, error); - notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, ResourceResponse(url, String(), -1, String(), String()), -1, error); + notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, ResourceResponse(url, String(), -1, String(), String()), -1, -1, error); url = request.url(); @@ -1947,7 +1977,7 @@ void FrameLoader::commitProvisionalLoad() // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing. // However, with today's computers and networking speeds, this won't happen in practice. // Could be an issue with a giant local file. - notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, response, static_cast<int>(response.expectedContentLength()), error); + notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, response, static_cast<int>(response.expectedContentLength()), 0, error); } pageCache()->remove(history()->currentItem()); @@ -1967,6 +1997,9 @@ void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage) if (m_state != FrameStateProvisional) return; + if (m_frame->view()) + m_frame->view()->scrollAnimator()->cancelAnimations(); + m_client->setCopiesOnScroll(); history()->updateForCommit(); @@ -2178,8 +2211,11 @@ void FrameLoader::open(CachedFrameBase& cachedFrame) view->setWasScrolledByUser(false); // Use the current ScrollView's frame rect. - if (m_frame->view()) - view->setFrameRect(m_frame->view()->frameRect()); + if (m_frame->view()) { + IntRect rect = m_frame->view()->frameRect(); + view->setFrameRect(rect); + view->setBoundsSize(rect.size()); + } m_frame->setView(view); m_frame->setDocument(document); @@ -2338,12 +2374,9 @@ CachePolicy FrameLoader::subresourceCachePolicy() const return parentCachePolicy; } - // FIXME: POST documents are always Reloads, but their subresources should still be Revalidate. - // If we bring the CachePolicy.h and ResourceRequest cache policy enums in sync with each other and - // remember "Revalidate" in ResourceRequests, we can remove this "POST" check and return either "Reload" - // or "Revalidate" if the DocumentLoader was requested with either. const ResourceRequest& request(documentLoader()->request()); - if (request.cachePolicy() == ReloadIgnoringCacheData && !equalIgnoringCase(request.httpMethod(), "post")) + Settings* settings = m_frame->settings(); + if (settings && settings->useQuickLookResourceCachingQuirks() && request.cachePolicy() == ReloadIgnoringCacheData && !equalIgnoringCase(request.httpMethod(), "post")) return CachePolicyRevalidate; if (m_loadType == FrameLoadTypeReload) @@ -2382,16 +2415,15 @@ void FrameLoader::checkLoadCompleteForThisFrame() // Only reset if we aren't already going to a new provisional item. bool shouldReset = !history()->provisionalItem(); - if (!(pdl->isLoadingInAPISense() && !pdl->isStopping())) { + if (!pdl->isLoadingInAPISense() || pdl->isStopping()) { m_delegateIsHandlingProvisionalLoadError = true; m_client->dispatchDidFailProvisionalLoad(error); m_delegateIsHandlingProvisionalLoadError = false; - // FIXME: can stopping loading here possibly have any effect, if isLoading is false, - // which it must be to be in this branch of the if? And is it OK to just do a full-on - // stopAllLoaders instead of stopLoadingSubframes? - stopLoadingSubframes(ShouldNotClearProvisionalItem); - pdl->stopLoading(); + ASSERT(!pdl->isLoading()); + ASSERT(!pdl->isLoadingMainResource()); + ASSERT(!pdl->isLoadingSubresources()); + ASSERT(!pdl->isLoadingPlugIns()); // If we're in the middle of loading multipart data, we need to restore the document loader. if (isReplacing() && !m_documentLoader.get()) @@ -2741,12 +2773,6 @@ void FrameLoader::loadPostRequest(const ResourceRequest& inRequest, const String { RefPtr<FormState> formState = prpFormState; - // When posting, use the NSURLRequestReloadIgnoringCacheData load flag. - // This prevents a potential bug which may cause a page with a form that uses itself - // as an action to be returned from the cache without submitting. - - // FIXME: Where's the code that implements what the comment above says? - // Previously when this method was reached, the original FrameLoadRequest had been deconstructed to build a // bunch of parameters that would come in here and then be built back up to a ResourceRequest. In case // any caller depends on the immutability of the original ResourceRequest, I'm rebuilding a ResourceRequest @@ -2813,8 +2839,7 @@ unsigned long FrameLoader::loadResourceSynchronously(const ResourceRequest& requ } #endif } - - notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, response, data.size(), error); + notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, response, data.size(), static_cast<int>(response.expectedContentLength()), error); return identifier; } @@ -3007,7 +3032,7 @@ void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest&, Pass if (!m_frame->page()) return; -#if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC) +#if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC) && ENABLE(INSPECTOR) if (Page* page = m_frame->page()) { if (page->mainFrame() == m_frame) m_frame->page()->inspectorController()->resume(); @@ -3107,7 +3132,7 @@ void FrameLoader::loadedResourceFromMemoryCache(const CachedResource* resource) ResourceError error; requestFromDelegate(request, identifier, error); InspectorInstrumentation::markResourceAsCached(page, identifier); - notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, resource->response(), resource->encodedSize(), error); + notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, resource->response(), resource->encodedSize(), 0, error); } void FrameLoader::applyUserAgent(ResourceRequest& request) diff --git a/Source/WebCore/loader/FrameLoader.h b/Source/WebCore/loader/FrameLoader.h index d59eb16..1fb9e3c 100644 --- a/Source/WebCore/loader/FrameLoader.h +++ b/Source/WebCore/loader/FrameLoader.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved. * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * Copyright (C) Research In Motion Limited 2009. All rights reserved. * @@ -35,6 +35,7 @@ #include "FrameLoaderStateMachine.h" #include "FrameLoaderTypes.h" #include "HistoryController.h" +#include "IconDatabaseBase.h" #include "PolicyChecker.h" #include "ResourceLoadNotifier.h" #include "SubframeLoader.h" @@ -289,13 +290,13 @@ public: FrameLoaderStateMachine* stateMachine() const { return &m_stateMachine; } - void iconLoadDecisionAvailable(); + void startIconLoader(); + void iconLoadDecisionReceived(IconLoadDecision); + void continueIconLoadWithDecision(IconLoadDecision); bool shouldAllowNavigation(Frame* targetFrame) const; Frame* findFrameForNavigation(const AtomicString& name); - void startIconLoader(); - void applyUserAgent(ResourceRequest& request); bool shouldInterruptLoadForXFrameOptions(const String&, const KURL&); @@ -322,7 +323,7 @@ public: bool suppressOpenerInNewFrame() const { return m_suppressOpenerInNewFrame; } - static ObjectContentType defaultObjectContentType(const KURL& url, const String& mimeType); + static ObjectContentType defaultObjectContentType(const KURL&, const String& mimeType, bool shouldPreferPlugInsForImages); void clear(bool clearWindowProperties = true, bool clearScriptObjects = true, bool clearFrameView = true); diff --git a/Source/WebCore/loader/FrameLoaderClient.h b/Source/WebCore/loader/FrameLoaderClient.h index 4a0bcbf..e89056d 100644 --- a/Source/WebCore/loader/FrameLoaderClient.h +++ b/Source/WebCore/loader/FrameLoaderClient.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -259,7 +259,7 @@ namespace WebCore { virtual void showMediaPlayerProxyPlugin(Widget*) = 0; #endif - virtual ObjectContentType objectContentType(const KURL& url, const String& mimeType) = 0; + virtual ObjectContentType objectContentType(const KURL&, const String& mimeType, bool shouldPreferPlugInsForImages) = 0; virtual String overrideMediaType() const = 0; virtual void dispatchDidClearWindowObjectInWorld(DOMWrapperWorld*) = 0; diff --git a/Source/WebCore/loader/FrameLoaderTypes.h b/Source/WebCore/loader/FrameLoaderTypes.h index 79c05dc..d13f375 100644 --- a/Source/WebCore/loader/FrameLoaderTypes.h +++ b/Source/WebCore/loader/FrameLoaderTypes.h @@ -42,7 +42,7 @@ namespace WebCore { enum PolicyAction { PolicyUse, PolicyDownload, - PolicyIgnore, + PolicyIgnore }; // NOTE: Keep in sync with WebKit/mac/WebView/WebFramePrivate.h and WebKit/win/Interfaces/IWebFramePrivate.idl diff --git a/Source/WebCore/loader/MainResourceLoader.cpp b/Source/WebCore/loader/MainResourceLoader.cpp index c3c8d62..0cdbc21 100644 --- a/Source/WebCore/loader/MainResourceLoader.cpp +++ b/Source/WebCore/loader/MainResourceLoader.cpp @@ -118,7 +118,9 @@ ResourceError MainResourceLoader::interruptionForPolicyChangeError() const void MainResourceLoader::stopLoadingForPolicyChange() { - cancel(interruptionForPolicyChangeError()); + ResourceError error = interruptionForPolicyChangeError(); + error.setIsCancellation(true); + cancel(error); } void MainResourceLoader::callContinueAfterNavigationPolicy(void* argument, const ResourceRequest& request, PassRefPtr<FormState>, bool shouldContinue) diff --git a/Source/WebCore/loader/PolicyCallback.cpp b/Source/WebCore/loader/PolicyCallback.cpp index 4ec2c84..45fdbb0 100644 --- a/Source/WebCore/loader/PolicyCallback.cpp +++ b/Source/WebCore/loader/PolicyCallback.cpp @@ -42,6 +42,7 @@ PolicyCallback::PolicyCallback() : m_navigationFunction(0) , m_newWindowFunction(0) , m_contentFunction(0) + , m_argument(0) { } diff --git a/Source/WebCore/loader/ResourceLoadNotifier.cpp b/Source/WebCore/loader/ResourceLoadNotifier.cpp index c928557..3a02aa3 100644 --- a/Source/WebCore/loader/ResourceLoadNotifier.cpp +++ b/Source/WebCore/loader/ResourceLoadNotifier.cpp @@ -74,12 +74,12 @@ void ResourceLoadNotifier::didReceiveResponse(ResourceLoader* loader, const Reso dispatchDidReceiveResponse(loader->documentLoader(), loader->identifier(), r); } -void ResourceLoadNotifier::didReceiveData(ResourceLoader* loader, const char* data, int length, int lengthReceived) +void ResourceLoadNotifier::didReceiveData(ResourceLoader* loader, const char* data, int dataLength, int lengthReceived) { if (Page* page = m_frame->page()) - page->progress()->incrementProgress(loader->identifier(), data, length); + page->progress()->incrementProgress(loader->identifier(), data, dataLength); - dispatchDidReceiveContentLength(loader->documentLoader(), loader->identifier(), lengthReceived); + dispatchDidReceiveContentLength(loader->documentLoader(), loader->identifier(), dataLength, lengthReceived); } void ResourceLoadNotifier::didFinishLoad(ResourceLoader* loader, double finishTime) @@ -103,8 +103,6 @@ void ResourceLoadNotifier::didFailToLoad(ResourceLoader* loader, const ResourceE void ResourceLoadNotifier::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request) { m_frame->loader()->client()->assignIdentifierToInitialRequest(identifier, loader, request); - - InspectorInstrumentation::identifierForInitialRequest(m_frame, identifier, loader, request); } void ResourceLoadNotifier::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse) @@ -118,7 +116,7 @@ void ResourceLoadNotifier::dispatchWillSendRequest(DocumentLoader* loader, unsig if (!request.isNull() && oldRequestURL != request.url().string().impl()) m_frame->loader()->documentLoader()->didTellClientAboutLoad(request.url()); - InspectorInstrumentation::willSendRequest(m_frame, identifier, request, redirectResponse); + InspectorInstrumentation::willSendRequest(m_frame, identifier, loader, request, redirectResponse); // Report WebTiming for all frames. if (loader && !request.isNull() && request.url() == loader->requestURL()) @@ -132,11 +130,11 @@ void ResourceLoadNotifier::dispatchDidReceiveResponse(DocumentLoader* loader, un InspectorInstrumentation::didReceiveResourceResponse(cookie, identifier, loader, r); } -void ResourceLoadNotifier::dispatchDidReceiveContentLength(DocumentLoader* loader, unsigned long identifier, int length) +void ResourceLoadNotifier::dispatchDidReceiveContentLength(DocumentLoader* loader, unsigned long identifier, int dataLength, int lengthReceived) { - m_frame->loader()->client()->dispatchDidReceiveContentLength(loader, identifier, length); + m_frame->loader()->client()->dispatchDidReceiveContentLength(loader, identifier, dataLength); - InspectorInstrumentation::didReceiveContentLength(m_frame, identifier, length); + InspectorInstrumentation::didReceiveContentLength(m_frame, identifier, dataLength, lengthReceived); } void ResourceLoadNotifier::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier, double finishTime) @@ -154,13 +152,13 @@ void ResourceLoadNotifier::dispatchTransferLoadingResourceFromPage(unsigned long oldPage->progress()->completeProgress(identifier); } -void ResourceLoadNotifier::sendRemainingDelegateMessages(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response, int length, const ResourceError& error) +void ResourceLoadNotifier::sendRemainingDelegateMessages(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response, int dataLength, int lengthReceived, const ResourceError& error) { if (!response.isNull()) dispatchDidReceiveResponse(loader, identifier, response); - if (length > 0) - dispatchDidReceiveContentLength(loader, identifier, length); + if (dataLength > 0) + dispatchDidReceiveContentLength(loader, identifier, dataLength, lengthReceived); if (error.isNull()) dispatchDidFinishLoading(loader, identifier, 0); diff --git a/Source/WebCore/loader/ResourceLoadNotifier.h b/Source/WebCore/loader/ResourceLoadNotifier.h index a6d92fb..5753c28 100644 --- a/Source/WebCore/loader/ResourceLoadNotifier.h +++ b/Source/WebCore/loader/ResourceLoadNotifier.h @@ -53,18 +53,18 @@ public: void willSendRequest(ResourceLoader*, ResourceRequest&, const ResourceResponse& redirectResponse); void didReceiveResponse(ResourceLoader*, const ResourceResponse&); - void didReceiveData(ResourceLoader*, const char*, int, int lengthReceived); + void didReceiveData(ResourceLoader*, const char*, int dataLength, int lengthReceived); void didFinishLoad(ResourceLoader*, double finishTime); void didFailToLoad(ResourceLoader*, const ResourceError&); void assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader*, const ResourceRequest&); void dispatchWillSendRequest(DocumentLoader*, unsigned long identifier, ResourceRequest&, const ResourceResponse& redirectResponse); void dispatchDidReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse&); - void dispatchDidReceiveContentLength(DocumentLoader*, unsigned long identifier, int length); + void dispatchDidReceiveContentLength(DocumentLoader*, unsigned long identifier, int dataLength, int lengthReceived); void dispatchDidFinishLoading(DocumentLoader*, unsigned long identifier, double finishTime); void dispatchTransferLoadingResourceFromPage(unsigned long, DocumentLoader*, const ResourceRequest&, Page*); - void sendRemainingDelegateMessages(DocumentLoader*, unsigned long identifier, const ResourceResponse&, int length, const ResourceError&); + void sendRemainingDelegateMessages(DocumentLoader*, unsigned long identifier, const ResourceResponse&, int dataLength, int lengthReceived, const ResourceError&); private: Frame* m_frame; diff --git a/Source/WebCore/loader/ResourceLoadScheduler.cpp b/Source/WebCore/loader/ResourceLoadScheduler.cpp index dbb6914..7cceff7 100644 --- a/Source/WebCore/loader/ResourceLoadScheduler.cpp +++ b/Source/WebCore/loader/ResourceLoadScheduler.cpp @@ -83,12 +83,13 @@ ResourceLoadScheduler::ResourceLoadScheduler() #endif } -PassRefPtr<SubresourceLoader> ResourceLoadScheduler::scheduleSubresourceLoad(Frame* frame, SubresourceLoaderClient* client, const ResourceRequest& request, ResourceLoadPriority priority, SecurityCheckPolicy securityCheck, bool sendResourceLoadCallbacks, bool shouldContentSniff) +PassRefPtr<SubresourceLoader> ResourceLoadScheduler::scheduleSubresourceLoad(Frame* frame, SubresourceLoaderClient* client, const ResourceRequest& request, ResourceLoadPriority priority, SecurityCheckPolicy securityCheck, + bool sendResourceLoadCallbacks, bool shouldContentSniff, const String& optionalOutgoingReferrer) { - PassRefPtr<SubresourceLoader> loader = SubresourceLoader::create(frame, client, request, securityCheck, sendResourceLoadCallbacks, shouldContentSniff); + RefPtr<SubresourceLoader> loader = SubresourceLoader::create(frame, client, request, securityCheck, sendResourceLoadCallbacks, shouldContentSniff, optionalOutgoingReferrer); if (loader) scheduleLoad(loader.get(), priority); - return loader; + return loader.release(); } PassRefPtr<NetscapePlugInStreamLoader> ResourceLoadScheduler::schedulePluginStreamLoad(Frame* frame, NetscapePlugInStreamLoaderClient* client, const ResourceRequest& request) diff --git a/Source/WebCore/loader/ResourceLoadScheduler.h b/Source/WebCore/loader/ResourceLoadScheduler.h index f2e627f..49a4546 100644 --- a/Source/WebCore/loader/ResourceLoadScheduler.h +++ b/Source/WebCore/loader/ResourceLoadScheduler.h @@ -32,6 +32,7 @@ #include <wtf/HashSet.h> #include <wtf/Noncopyable.h> #include <wtf/text/StringHash.h> +#include <wtf/text/WTFString.h> namespace WebCore { @@ -49,7 +50,7 @@ class ResourceLoadScheduler { public: friend ResourceLoadScheduler* resourceLoadScheduler(); - PassRefPtr<SubresourceLoader> scheduleSubresourceLoad(Frame*, SubresourceLoaderClient*, const ResourceRequest&, ResourceLoadPriority = ResourceLoadPriorityLow, SecurityCheckPolicy = DoSecurityCheck, bool sendResourceLoadCallbacks = true, bool shouldContentSniff = true); + PassRefPtr<SubresourceLoader> scheduleSubresourceLoad(Frame*, SubresourceLoaderClient*, const ResourceRequest&, ResourceLoadPriority = ResourceLoadPriorityLow, SecurityCheckPolicy = DoSecurityCheck, bool sendResourceLoadCallbacks = true, bool shouldContentSniff = true, const String& optionalOutgoingReferrer = String()); PassRefPtr<NetscapePlugInStreamLoader> schedulePluginStreamLoad(Frame*, NetscapePlugInStreamLoaderClient*, const ResourceRequest&); void addMainResourceLoad(ResourceLoader*); void remove(ResourceLoader*); diff --git a/Source/WebCore/loader/ResourceLoader.h b/Source/WebCore/loader/ResourceLoader.h index e5c5d3f..339b130 100644 --- a/Source/WebCore/loader/ResourceLoader.h +++ b/Source/WebCore/loader/ResourceLoader.h @@ -88,6 +88,9 @@ namespace WebCore { void willStopBufferingData(const char*, int); virtual void didFinishLoading(double finishTime); virtual void didFail(const ResourceError&); +#if HAVE(CFNETWORK_DATA_ARRAY_CALLBACK) + virtual void didReceiveDataArray(CFArrayRef dataArray); +#endif virtual bool shouldUseCredentialStorage(); virtual void didReceiveAuthenticationChallenge(const AuthenticationChallenge&); @@ -111,6 +114,9 @@ namespace WebCore { virtual bool shouldUseCredentialStorage(ResourceHandle*) { return shouldUseCredentialStorage(); } virtual void didReceiveAuthenticationChallenge(ResourceHandle*, const AuthenticationChallenge& challenge) { didReceiveAuthenticationChallenge(challenge); } virtual void didCancelAuthenticationChallenge(ResourceHandle*, const AuthenticationChallenge& challenge) { didCancelAuthenticationChallenge(challenge); } +#if HAVE(CFNETWORK_DATA_ARRAY_CALLBACK) + virtual void didReceiveDataArray(ResourceHandle*, CFArrayRef dataArray); +#endif #if USE(PROTECTION_SPACE_AUTH_CALLBACK) virtual bool canAuthenticateAgainstProtectionSpace(ResourceHandle*, const ProtectionSpace& protectionSpace) { return canAuthenticateAgainstProtectionSpace(protectionSpace); } #endif diff --git a/Source/WebCore/loader/SubframeLoader.cpp b/Source/WebCore/loader/SubframeLoader.cpp index 8bfd474..e7f851f 100644 --- a/Source/WebCore/loader/SubframeLoader.cpp +++ b/Source/WebCore/loader/SubframeLoader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * Copyright (C) 2008 Alp Toker <alp@atoker.com> @@ -88,17 +88,35 @@ bool SubframeLoader::requestFrame(HTMLFrameOwnerElement* ownerElement, const Str return true; } -bool SubframeLoader::resourceWillUsePlugin(const String& url, const String& mimeType) +bool SubframeLoader::resourceWillUsePlugin(const String& url, const String& mimeType, bool shouldPreferPlugInsForImages) { KURL completedURL; if (!url.isEmpty()) completedURL = completeURL(url); + bool useFallback; - return shouldUsePlugin(completedURL, mimeType, false, useFallback); + return shouldUsePlugin(completedURL, mimeType, shouldPreferPlugInsForImages, false, useFallback); } -bool SubframeLoader::requestObject(HTMLPlugInImageElement* ownerElement, const String& url, const AtomicString& frameName, - const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues) +bool SubframeLoader::requestPlugin(HTMLPlugInImageElement* ownerElement, const KURL& url, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback) +{ + Settings* settings = m_frame->settings(); + if ((!allowPlugins(AboutToInstantiatePlugin) + // Application plug-ins are plug-ins implemented by the user agent, for example Qt plug-ins, + // as opposed to third-party code such as Flash. The user agent decides whether or not they are + // permitted, rather than WebKit. + && !MIMETypeRegistry::isApplicationPluginMIMEType(mimeType)) + || (!settings->isJavaEnabled() && MIMETypeRegistry::isJavaAppletMIMEType(mimeType))) + return false; + + if (m_frame->document() && m_frame->document()->securityOrigin()->isSandboxed(SandboxPlugins)) + return false; + + ASSERT(ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag)); + return loadPlugin(ownerElement, url, mimeType, paramNames, paramValues, useFallback); +} + +bool SubframeLoader::requestObject(HTMLPlugInImageElement* ownerElement, const String& url, const AtomicString& frameName, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues) { if (url.isEmpty() && mimeType.isEmpty()) return false; @@ -114,23 +132,8 @@ bool SubframeLoader::requestObject(HTMLPlugInImageElement* ownerElement, const S completedURL = completeURL(url); bool useFallback; - if (shouldUsePlugin(completedURL, mimeType, renderer->hasFallbackContent(), useFallback)) { - Settings* settings = m_frame->settings(); - if ((!allowPlugins(AboutToInstantiatePlugin) - // Application plugins are plugins implemented by the user agent, for example Qt plugins, - // as opposed to third-party code such as flash. The user agent decides whether or not they are - // permitted, rather than WebKit. - && !MIMETypeRegistry::isApplicationPluginMIMEType(mimeType)) - || (!settings->isJavaEnabled() && MIMETypeRegistry::isJavaAppletMIMEType(mimeType))) - return false; - if (m_frame->document() && m_frame->document()->securityOrigin()->isSandboxed(SandboxPlugins)) - return false; - - ASSERT(ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag)); - HTMLPlugInImageElement* pluginElement = static_cast<HTMLPlugInImageElement*>(ownerElement); - - return loadPlugin(pluginElement, completedURL, mimeType, paramNames, paramValues, useFallback); - } + if (shouldUsePlugin(completedURL, mimeType, ownerElement->shouldPreferPlugInsForImages(), renderer->hasFallbackContent(), useFallback)) + return requestPlugin(ownerElement, completedURL, mimeType, paramNames, paramValues, useFallback); // If the plug-in element already contains a subframe, loadOrRedirectSubframe will re-use it. Otherwise, // it will create a new frame and set it as the RenderPart's widget, causing what was previously @@ -289,7 +292,7 @@ bool SubframeLoader::allowPlugins(ReasonForCallingAllowPlugins reason) return allowed; } -bool SubframeLoader::shouldUsePlugin(const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback) +bool SubframeLoader::shouldUsePlugin(const KURL& url, const String& mimeType, bool shouldPreferPlugInsForImages, bool hasFallback, bool& useFallback) { if (m_frame->loader()->client()->shouldUsePluginDocument(mimeType)) { useFallback = false; @@ -305,7 +308,7 @@ bool SubframeLoader::shouldUsePlugin(const KURL& url, const String& mimeType, bo return true; } - ObjectContentType objectType = m_frame->loader()->client()->objectContentType(url, mimeType); + ObjectContentType objectType = m_frame->loader()->client()->objectContentType(url, mimeType, shouldPreferPlugInsForImages); // If an object's content can't be handled and it has no fallback, let // it be handled as a plugin to show the broken plugin icon. useFallback = objectType == ObjectContentNone && hasFallback; diff --git a/Source/WebCore/loader/SubframeLoader.h b/Source/WebCore/loader/SubframeLoader.h index ba63a5c..01c59e6 100644 --- a/Source/WebCore/loader/SubframeLoader.h +++ b/Source/WebCore/loader/SubframeLoader.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved. * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * Copyright (C) Research In Motion Limited 2009. All rights reserved. * @@ -77,15 +77,16 @@ public: bool containsPlugins() const { return m_containsPlugins; } - bool resourceWillUsePlugin(const String& url, const String& mimeType); + bool resourceWillUsePlugin(const String& url, const String& mimeType, bool shouldPreferPlugInsForImages); private: + bool requestPlugin(HTMLPlugInImageElement*, const KURL&, const String& serviceType, const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback); Frame* loadOrRedirectSubframe(HTMLFrameOwnerElement*, const KURL&, const AtomicString& frameName, bool lockHistory, bool lockBackForwardList); Frame* loadSubframe(HTMLFrameOwnerElement*, const KURL&, const String& name, const String& referrer); bool loadPlugin(HTMLPlugInImageElement*, const KURL&, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback); - bool shouldUsePlugin(const KURL&, const String& mimeType, bool hasFallback, bool& useFallback); + bool shouldUsePlugin(const KURL&, const String& mimeType, bool shouldPreferPlugInsForImages, bool hasFallback, bool& useFallback); Document* document() const; diff --git a/Source/WebCore/loader/SubresourceLoader.cpp b/Source/WebCore/loader/SubresourceLoader.cpp index f948ec3..cfe8d0a 100644 --- a/Source/WebCore/loader/SubresourceLoader.cpp +++ b/Source/WebCore/loader/SubresourceLoader.cpp @@ -60,7 +60,7 @@ SubresourceLoader::~SubresourceLoader() #endif } -PassRefPtr<SubresourceLoader> SubresourceLoader::create(Frame* frame, SubresourceLoaderClient* client, const ResourceRequest& request, SecurityCheckPolicy securityCheck, bool sendResourceLoadCallbacks, bool shouldContentSniff) +PassRefPtr<SubresourceLoader> SubresourceLoader::create(Frame* frame, SubresourceLoaderClient* client, const ResourceRequest& request, SecurityCheckPolicy securityCheck, bool sendResourceLoadCallbacks, bool shouldContentSniff, const String& optionalOutgoingReferrer) { if (!frame) return 0; @@ -75,12 +75,22 @@ PassRefPtr<SubresourceLoader> SubresourceLoader::create(Frame* frame, Subresourc FrameLoader::reportLocalLoadFailed(frame, request.url().string()); return 0; } - - if (SecurityOrigin::shouldHideReferrer(request.url(), fl->outgoingReferrer())) + + String outgoingReferrer; + String outgoingOrigin; + if (optionalOutgoingReferrer.isNull()) { + outgoingReferrer = fl->outgoingReferrer(); + outgoingOrigin = fl->outgoingOrigin(); + } else { + outgoingReferrer = optionalOutgoingReferrer; + outgoingOrigin = SecurityOrigin::createFromString(outgoingReferrer)->toString(); + } + + if (SecurityOrigin::shouldHideReferrer(request.url(), outgoingReferrer)) newRequest.clearHTTPReferrer(); else if (!request.httpReferrer()) - newRequest.setHTTPReferrer(fl->outgoingReferrer()); - FrameLoader::addHTTPOriginIfNeeded(newRequest, fl->outgoingOrigin()); + newRequest.setHTTPReferrer(outgoingReferrer); + FrameLoader::addHTTPOriginIfNeeded(newRequest, outgoingOrigin); fl->addExtraFieldsToSubresourceRequest(newRequest); diff --git a/Source/WebCore/loader/SubresourceLoader.h b/Source/WebCore/loader/SubresourceLoader.h index cb7ed81..b3aefb6 100644 --- a/Source/WebCore/loader/SubresourceLoader.h +++ b/Source/WebCore/loader/SubresourceLoader.h @@ -31,6 +31,8 @@ #include "FrameLoaderTypes.h" #include "ResourceLoader.h" + +#include <wtf/text/WTFString.h> namespace WebCore { @@ -39,7 +41,7 @@ namespace WebCore { class SubresourceLoader : public ResourceLoader { public: - static PassRefPtr<SubresourceLoader> create(Frame*, SubresourceLoaderClient*, const ResourceRequest&, SecurityCheckPolicy = DoSecurityCheck, bool sendResourceLoadCallbacks = true, bool shouldContentSniff = true); + static PassRefPtr<SubresourceLoader> create(Frame*, SubresourceLoaderClient*, const ResourceRequest&, SecurityCheckPolicy = DoSecurityCheck, bool sendResourceLoadCallbacks = true, bool shouldContentSniff = true, const String& optionalOutgoingReferrer = String()); void clearClient() { m_client = 0; } @@ -59,6 +61,11 @@ namespace WebCore { virtual void receivedCancellation(const AuthenticationChallenge&); virtual void didCancel(const ResourceError&); +#if HAVE(CFNETWORK_DATA_ARRAY_CALLBACK) + virtual bool supportsDataArray() { return true; } + virtual void didReceiveDataArray(CFArrayRef); +#endif + SubresourceLoaderClient* m_client; bool m_loadingMultipartContent; }; diff --git a/Source/WebCore/loader/ThreadableLoaderClientWrapper.h b/Source/WebCore/loader/ThreadableLoaderClientWrapper.h index 664e0b3..d765fa0 100644 --- a/Source/WebCore/loader/ThreadableLoaderClientWrapper.h +++ b/Source/WebCore/loader/ThreadableLoaderClientWrapper.h @@ -38,85 +38,85 @@ namespace WebCore { - class ThreadableLoaderClientWrapper : public ThreadSafeShared<ThreadableLoaderClientWrapper> { - public: - static PassRefPtr<ThreadableLoaderClientWrapper> create(ThreadableLoaderClient* client) - { - return adoptRef(new ThreadableLoaderClientWrapper(client)); - } - - void clearClient() - { - m_done = true; - m_client = 0; - } - - bool done() const - { - return m_done; - } - - void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) - { - if (m_client) - m_client->didSendData(bytesSent, totalBytesToBeSent); - } - - void didReceiveResponse(const ResourceResponse& response) - { - if (m_client) - m_client->didReceiveResponse(response); - } - - void didReceiveData(const char* data, int dataLength) - { - if (m_client) - m_client->didReceiveData(data, dataLength); - } - - void didReceiveCachedMetadata(const char* data, int dataLength) - { - if (m_client) - m_client->didReceiveCachedMetadata(data, dataLength); - } - - void didFinishLoading(unsigned long identifier, double finishTime) - { - m_done = true; - if (m_client) - m_client->didFinishLoading(identifier, finishTime); - } - - void didFail(const ResourceError& error) - { - m_done = true; - if (m_client) - m_client->didFail(error); - } - - void didFailRedirectCheck() - { - m_done = true; - if (m_client) - m_client->didFailRedirectCheck(); - } - - void didReceiveAuthenticationCancellation(const ResourceResponse& response) - { - if (m_client) - m_client->didReceiveResponse(response); - } - - protected: - ThreadableLoaderClientWrapper(ThreadableLoaderClient* client) - : m_client(client) - , m_done(false) - { - } - - ThreadableLoaderClient* m_client; - bool m_done; - }; +class ThreadableLoaderClientWrapper : public ThreadSafeRefCounted<ThreadableLoaderClientWrapper> { +public: + static PassRefPtr<ThreadableLoaderClientWrapper> create(ThreadableLoaderClient* client) + { + return adoptRef(new ThreadableLoaderClientWrapper(client)); + } + + void clearClient() + { + m_done = true; + m_client = 0; + } + + bool done() const + { + return m_done; + } + + void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) + { + if (m_client) + m_client->didSendData(bytesSent, totalBytesToBeSent); + } + + void didReceiveResponse(const ResourceResponse& response) + { + if (m_client) + m_client->didReceiveResponse(response); + } + + void didReceiveData(const char* data, int dataLength) + { + if (m_client) + m_client->didReceiveData(data, dataLength); + } + + void didReceiveCachedMetadata(const char* data, int dataLength) + { + if (m_client) + m_client->didReceiveCachedMetadata(data, dataLength); + } + + void didFinishLoading(unsigned long identifier, double finishTime) + { + m_done = true; + if (m_client) + m_client->didFinishLoading(identifier, finishTime); + } + + void didFail(const ResourceError& error) + { + m_done = true; + if (m_client) + m_client->didFail(error); + } + + void didFailRedirectCheck() + { + m_done = true; + if (m_client) + m_client->didFailRedirectCheck(); + } + + void didReceiveAuthenticationCancellation(const ResourceResponse& response) + { + if (m_client) + m_client->didReceiveResponse(response); + } + +protected: + ThreadableLoaderClientWrapper(ThreadableLoaderClient* client) + : m_client(client) + , m_done(false) + { + } + + ThreadableLoaderClient* m_client; + bool m_done; +}; } // namespace WebCore diff --git a/Source/WebCore/loader/WorkerThreadableLoader.cpp b/Source/WebCore/loader/WorkerThreadableLoader.cpp index 6c61318..d753ecb 100644 --- a/Source/WebCore/loader/WorkerThreadableLoader.cpp +++ b/Source/WebCore/loader/WorkerThreadableLoader.cpp @@ -34,6 +34,8 @@ #include "WorkerThreadableLoader.h" +#include "Document.h" +#include "DocumentThreadableLoader.h" #include "CrossThreadTask.h" #include "ResourceError.h" #include "ResourceRequest.h" @@ -55,7 +57,7 @@ static const char loadResourceSynchronouslyMode[] = "loadResourceSynchronouslyMo WorkerThreadableLoader::WorkerThreadableLoader(WorkerContext* workerContext, ThreadableLoaderClient* client, const String& taskMode, const ResourceRequest& request, const ThreadableLoaderOptions& options) : m_workerContext(workerContext) , m_workerClientWrapper(ThreadableLoaderClientWrapper::create(client)) - , m_bridge(*(new MainThreadBridge(m_workerClientWrapper, m_workerContext->thread()->workerLoaderProxy(), taskMode, request, options))) + , m_bridge(*(new MainThreadBridge(m_workerClientWrapper, m_workerContext->thread()->workerLoaderProxy(), taskMode, request, options, workerContext->url().strippedForUseAsReferrer()))) { } @@ -87,32 +89,30 @@ void WorkerThreadableLoader::cancel() } WorkerThreadableLoader::MainThreadBridge::MainThreadBridge(PassRefPtr<ThreadableLoaderClientWrapper> workerClientWrapper, WorkerLoaderProxy& loaderProxy, const String& taskMode, - const ResourceRequest& request, const ThreadableLoaderOptions& options) + const ResourceRequest& request, const ThreadableLoaderOptions& options, const String& outgoingReferrer) : m_workerClientWrapper(workerClientWrapper) , m_loaderProxy(loaderProxy) , m_taskMode(taskMode.crossThreadString()) { ASSERT(m_workerClientWrapper.get()); - m_loaderProxy.postTaskToLoader(createCallbackTask(&MainThreadBridge::mainThreadCreateLoader, this, request, options)); + m_loaderProxy.postTaskToLoader(createCallbackTask(&MainThreadBridge::mainThreadCreateLoader, this, request, options, outgoingReferrer)); } WorkerThreadableLoader::MainThreadBridge::~MainThreadBridge() { } -void WorkerThreadableLoader::MainThreadBridge::mainThreadCreateLoader(ScriptExecutionContext* context, MainThreadBridge* thisPtr, PassOwnPtr<CrossThreadResourceRequestData> requestData, ThreadableLoaderOptions options) +void WorkerThreadableLoader::MainThreadBridge::mainThreadCreateLoader(ScriptExecutionContext* context, MainThreadBridge* thisPtr, PassOwnPtr<CrossThreadResourceRequestData> requestData, ThreadableLoaderOptions options, const String& outgoingReferrer) { ASSERT(isMainThread()); ASSERT(context->isDocument()); + Document* document = static_cast<Document*>(context); - // FIXME: the created loader has no knowledge of the origin of the worker doing the load request. - // Basically every setting done in SubresourceLoader::create (including the contents of addExtraFieldsToRequest) - // needs to be examined for how it should take into account a different originator. OwnPtr<ResourceRequest> request(ResourceRequest::adopt(requestData)); // FIXME: If the a site requests a local resource, then this will return a non-zero value but the sync path // will return a 0 value. Either this should return 0 or the other code path should do a callback with // a failure. - thisPtr->m_mainThreadLoader = ThreadableLoader::create(context, thisPtr, *request, options); + thisPtr->m_mainThreadLoader = DocumentThreadableLoader::create(document, thisPtr, *request, options, outgoingReferrer); ASSERT(thisPtr->m_mainThreadLoader); } diff --git a/Source/WebCore/loader/WorkerThreadableLoader.h b/Source/WebCore/loader/WorkerThreadableLoader.h index 2477f19..7685eed 100644 --- a/Source/WebCore/loader/WorkerThreadableLoader.h +++ b/Source/WebCore/loader/WorkerThreadableLoader.h @@ -98,7 +98,7 @@ namespace WebCore { class MainThreadBridge : public ThreadableLoaderClient { public: // All executed on the worker context's thread. - MainThreadBridge(PassRefPtr<ThreadableLoaderClientWrapper>, WorkerLoaderProxy&, const String& taskMode, const ResourceRequest&, const ThreadableLoaderOptions&); + MainThreadBridge(PassRefPtr<ThreadableLoaderClientWrapper>, WorkerLoaderProxy&, const String& taskMode, const ResourceRequest&, const ThreadableLoaderOptions&, const String& outgoingReferrer); void cancel(); void destroy(); @@ -110,7 +110,7 @@ namespace WebCore { static void mainThreadDestroy(ScriptExecutionContext*, MainThreadBridge*); ~MainThreadBridge(); - static void mainThreadCreateLoader(ScriptExecutionContext*, MainThreadBridge*, PassOwnPtr<CrossThreadResourceRequestData>, ThreadableLoaderOptions); + static void mainThreadCreateLoader(ScriptExecutionContext*, MainThreadBridge*, PassOwnPtr<CrossThreadResourceRequestData>, ThreadableLoaderOptions, const String& outgoingReferrer); static void mainThreadCancel(ScriptExecutionContext*, MainThreadBridge*); virtual void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent); virtual void didReceiveResponse(const ResourceResponse&); diff --git a/Source/WebCore/loader/appcache/ApplicationCache.cpp b/Source/WebCore/loader/appcache/ApplicationCache.cpp index 450fa10..f3479b4 100644 --- a/Source/WebCore/loader/appcache/ApplicationCache.cpp +++ b/Source/WebCore/loader/appcache/ApplicationCache.cpp @@ -32,6 +32,7 @@ #include "ApplicationCacheResource.h" #include "ApplicationCacheStorage.h" #include "ResourceRequest.h" +#include "SecurityOrigin.h" #include <wtf/text/CString.h> #include <stdio.h> @@ -182,7 +183,29 @@ void ApplicationCache::clearStorageID() ResourceMap::const_iterator end = m_resources.end(); for (ResourceMap::const_iterator it = m_resources.begin(); it != end; ++it) it->second->clearStorageID(); -} +} + +void ApplicationCache::deleteCacheForOrigin(SecurityOrigin* origin) +{ + Vector<KURL> urls; + if (!cacheStorage().manifestURLs(&urls)) { + LOG_ERROR("Failed to retrieve ApplicationCache manifest URLs"); + return; + } + + KURL originURL(KURL(), origin->toString()); + + size_t count = urls.size(); + for (size_t i = 0; i < count; ++i) { + if (protocolHostAndPortAreEqual(urls[i], originURL)) { + ApplicationCacheGroup* group = cacheStorage().findInMemoryCacheGroup(urls[i]); + if (group) + group->makeObsolete(); + else + cacheStorage().deleteCacheGroup(urls[i]); + } + } +} #ifndef NDEBUG void ApplicationCache::dump() diff --git a/Source/WebCore/loader/appcache/ApplicationCache.h b/Source/WebCore/loader/appcache/ApplicationCache.h index f073499..9d20361 100644 --- a/Source/WebCore/loader/appcache/ApplicationCache.h +++ b/Source/WebCore/loader/appcache/ApplicationCache.h @@ -42,12 +42,16 @@ class ApplicationCacheResource; class DocumentLoader; class KURL; class ResourceRequest; +class SecurityOrigin; typedef Vector<std::pair<KURL, KURL> > FallbackURLVector; class ApplicationCache : public RefCounted<ApplicationCache> { public: static PassRefPtr<ApplicationCache> create() { return adoptRef(new ApplicationCache); } + + static void deleteCacheForOrigin(SecurityOrigin*); + ~ApplicationCache(); void addResource(PassRefPtr<ApplicationCacheResource> resource); diff --git a/Source/WebCore/loader/appcache/ApplicationCacheGroup.cpp b/Source/WebCore/loader/appcache/ApplicationCacheGroup.cpp index 514ef19..aab8927 100644 --- a/Source/WebCore/loader/appcache/ApplicationCacheGroup.cpp +++ b/Source/WebCore/loader/appcache/ApplicationCacheGroup.cpp @@ -474,9 +474,8 @@ PassRefPtr<ResourceHandle> ApplicationCacheGroup::createResourceHandle(const KUR // Because willSendRequest only gets called during redirects, we initialize // the identifier and the first willSendRequest here. m_currentResourceIdentifier = m_frame->page()->progress()->createUniqueIdentifier(); - InspectorInstrumentation::identifierForInitialRequest(m_frame, m_currentResourceIdentifier, m_frame->loader()->documentLoader(), handle->firstRequest()); ResourceResponse redirectResponse = ResourceResponse(); - InspectorInstrumentation::willSendRequest(m_frame, m_currentResourceIdentifier, request, redirectResponse); + InspectorInstrumentation::willSendRequest(m_frame, m_currentResourceIdentifier, m_frame->loader()->documentLoader(), request, redirectResponse); #endif return handle; } @@ -512,7 +511,7 @@ void ApplicationCacheGroup::didReceiveResponse(ResourceHandle* handle, const Res if (m_newestCache && response.httpStatusCode() == 304) { // Not modified. ApplicationCacheResource* newestCachedResource = m_newestCache->resourceForURL(url); if (newestCachedResource) { - m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, newestCachedResource->response(), type, newestCachedResource->data())); + m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, newestCachedResource->response(), type, newestCachedResource->data(), newestCachedResource->path())); m_pendingEntries.remove(m_currentHandle->firstRequest().url()); m_currentHandle->cancel(); m_currentHandle = 0; @@ -540,7 +539,7 @@ void ApplicationCacheGroup::didReceiveResponse(ResourceHandle* handle, const Res ASSERT(m_newestCache); ApplicationCacheResource* newestCachedResource = m_newestCache->resourceForURL(handle->firstRequest().url()); ASSERT(newestCachedResource); - m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, newestCachedResource->response(), type, newestCachedResource->data())); + m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, newestCachedResource->response(), type, newestCachedResource->data(), newestCachedResource->path())); m_pendingEntries.remove(m_currentHandle->firstRequest().url()); m_currentHandle->cancel(); m_currentHandle = 0; @@ -555,8 +554,10 @@ void ApplicationCacheGroup::didReceiveResponse(ResourceHandle* handle, const Res void ApplicationCacheGroup::didReceiveData(ResourceHandle* handle, const char* data, int length, int lengthReceived) { + UNUSED_PARAM(lengthReceived); + #if ENABLE(INSPECTOR) - InspectorInstrumentation::didReceiveContentLength(m_frame, m_currentResourceIdentifier, lengthReceived); + InspectorInstrumentation::didReceiveContentLength(m_frame, m_currentResourceIdentifier, length, 0); #endif if (handle == m_manifestHandle) { @@ -642,7 +643,7 @@ void ApplicationCacheGroup::didFail(ResourceHandle* handle, const ResourceError& ASSERT(m_newestCache); ApplicationCacheResource* newestCachedResource = m_newestCache->resourceForURL(url); ASSERT(newestCachedResource); - m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, newestCachedResource->response(), type, newestCachedResource->data())); + m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, newestCachedResource->response(), type, newestCachedResource->data(), newestCachedResource->path())); // Load the next resource, if any. startLoadingEntry(); } @@ -866,7 +867,7 @@ void ApplicationCacheGroup::checkIfLoadIsComplete() } ApplicationCacheStorage::FailureReason failureReason; - RefPtr<ApplicationCache> oldNewestCache = (m_newestCache == m_cacheBeingUpdated) ? 0 : m_newestCache; + RefPtr<ApplicationCache> oldNewestCache = (m_newestCache == m_cacheBeingUpdated) ? RefPtr<ApplicationCache>() : m_newestCache; setNewestCache(m_cacheBeingUpdated.release()); if (cacheStorage().storeNewestCache(this, oldNewestCache.get(), failureReason)) { // New cache stored, now remove the old cache. diff --git a/Source/WebCore/loader/appcache/ApplicationCacheHost.h b/Source/WebCore/loader/appcache/ApplicationCacheHost.h index a1f2841..56a5f57 100644 --- a/Source/WebCore/loader/appcache/ApplicationCacheHost.h +++ b/Source/WebCore/loader/appcache/ApplicationCacheHost.h @@ -156,6 +156,11 @@ namespace WebCore { CacheInfo applicationCacheInfo(); #endif +#if !PLATFORM(CHROMIUM) + bool shouldLoadResourceFromApplicationCache(const ResourceRequest&, ApplicationCacheResource*&); + bool getApplicationCacheFallbackResource(const ResourceRequest&, ApplicationCacheResource*&, ApplicationCache* = 0); +#endif + private: bool isApplicationCacheEnabled(); DocumentLoader* documentLoader() const { return m_documentLoader; } @@ -182,8 +187,6 @@ namespace WebCore { friend class ApplicationCacheStorage; bool scheduleLoadFallbackResourceFromApplicationCache(ResourceLoader*, ApplicationCache* = 0); - bool shouldLoadResourceFromApplicationCache(const ResourceRequest&, ApplicationCacheResource*&); - bool getApplicationCacheFallbackResource(const ResourceRequest&, ApplicationCacheResource*&, ApplicationCache* = 0); void setCandidateApplicationCacheGroup(ApplicationCacheGroup* group); ApplicationCacheGroup* candidateApplicationCacheGroup() const { return m_candidateApplicationCacheGroup; } void setApplicationCache(PassRefPtr<ApplicationCache> applicationCache); diff --git a/Source/WebCore/loader/appcache/ApplicationCacheResource.cpp b/Source/WebCore/loader/appcache/ApplicationCacheResource.cpp index 03c5c83..c0df573 100644 --- a/Source/WebCore/loader/appcache/ApplicationCacheResource.cpp +++ b/Source/WebCore/loader/appcache/ApplicationCacheResource.cpp @@ -31,11 +31,12 @@ namespace WebCore { -ApplicationCacheResource::ApplicationCacheResource(const KURL& url, const ResourceResponse& response, unsigned type, PassRefPtr<SharedBuffer> data) +ApplicationCacheResource::ApplicationCacheResource(const KURL& url, const ResourceResponse& response, unsigned type, PassRefPtr<SharedBuffer> data, const String& path) : SubstituteResource(url, response, data) , m_type(type) , m_storageID(0) , m_estimatedSizeInStorage(0) + , m_path(path) { } diff --git a/Source/WebCore/loader/appcache/ApplicationCacheResource.h b/Source/WebCore/loader/appcache/ApplicationCacheResource.h index 2ca7846..6633c6c 100644 --- a/Source/WebCore/loader/appcache/ApplicationCacheResource.h +++ b/Source/WebCore/loader/appcache/ApplicationCacheResource.h @@ -42,10 +42,10 @@ public: Fallback = 1 << 4 }; - static PassRefPtr<ApplicationCacheResource> create(const KURL& url, const ResourceResponse& response, unsigned type, PassRefPtr<SharedBuffer> buffer = SharedBuffer::create()) + static PassRefPtr<ApplicationCacheResource> create(const KURL& url, const ResourceResponse& response, unsigned type, PassRefPtr<SharedBuffer> buffer = SharedBuffer::create(), const String& path = String()) { ASSERT(!url.hasFragmentIdentifier()); - return adoptRef(new ApplicationCacheResource(url, response, type, buffer)); + return adoptRef(new ApplicationCacheResource(url, response, type, buffer, path)); } unsigned type() const { return m_type; } @@ -56,16 +56,20 @@ public: void clearStorageID() { m_storageID = 0; } int64_t estimatedSizeInStorage(); + const String& path() const { return m_path; } + void setPath(const String& path) { m_path = path; } + #ifndef NDEBUG static void dumpType(unsigned type); #endif private: - ApplicationCacheResource(const KURL& url, const ResourceResponse& response, unsigned type, PassRefPtr<SharedBuffer> buffer); + ApplicationCacheResource(const KURL&, const ResourceResponse&, unsigned type, PassRefPtr<SharedBuffer>, const String& path); unsigned m_type; unsigned m_storageID; int64_t m_estimatedSizeInStorage; + String m_path; }; } // namespace WebCore diff --git a/Source/WebCore/loader/appcache/ApplicationCacheStorage.cpp b/Source/WebCore/loader/appcache/ApplicationCacheStorage.cpp index 5c6937e..a126f8a 100644 --- a/Source/WebCore/loader/appcache/ApplicationCacheStorage.cpp +++ b/Source/WebCore/loader/appcache/ApplicationCacheStorage.cpp @@ -38,6 +38,7 @@ #include "SQLiteStatement.h" #include "SQLiteTransaction.h" #include "SecurityOrigin.h" +#include "UUID.h" #include <wtf/text/CString.h> #include <wtf/StdLibExtras.h> #include <wtf/StringExtras.h> @@ -46,6 +47,8 @@ using namespace std; namespace WebCore { +static const char flatFileSubdirectory[] = "ApplicationCache"; + template <class T> class StorageIDJournal { public: @@ -90,7 +93,7 @@ static unsigned urlHostHash(const KURL& url) unsigned hostStart = url.hostStart(); unsigned hostEnd = url.hostEnd(); - return AlreadyHashed::avoidDeletedValue(WTF::StringHasher::createHash(url.string().characters() + hostStart, hostEnd - hostStart)); + return AlreadyHashed::avoidDeletedValue(StringHasher::computeHash(url.string().characters() + hostStart, hostEnd - hostStart)); } ApplicationCacheGroup* ApplicationCacheStorage::loadCacheGroup(const KURL& manifestURL) @@ -153,6 +156,11 @@ ApplicationCacheGroup* ApplicationCacheStorage::findOrCreateCacheGroup(const KUR return group; } +ApplicationCacheGroup* ApplicationCacheStorage::findInMemoryCacheGroup(const KURL& manifestURL) const +{ + return m_cachesInMemory.get(manifestURL); +} + void ApplicationCacheStorage::loadManifestHostHashes() { static bool hasLoadedHashes = false; @@ -389,7 +397,7 @@ int64_t ApplicationCacheStorage::spaceNeeded(int64_t cacheToSave) if (!getFileSize(m_cacheFile, fileSize)) return 0; - int64_t currentSize = fileSize; + int64_t currentSize = fileSize + flatFileAreaSize(); // Determine the amount of free space we have available. int64_t totalAvailableSize = 0; @@ -555,7 +563,7 @@ bool ApplicationCacheStorage::executeSQLCommand(const String& sql) // Update the schemaVersion when the schema of any the Application Cache // SQLite tables changes. This allows the database to be rebuilt when // a new, incompatible change has been introduced to the database schema. -static const int schemaVersion = 6; +static const int schemaVersion = 7; void ApplicationCacheStorage::verifySchemaVersion() { @@ -563,7 +571,7 @@ void ApplicationCacheStorage::verifySchemaVersion() if (version == schemaVersion) return; - m_database.clearAllTables(); + deleteTables(); // Update user version. SQLiteTransaction setDatabaseVersion(m_database); @@ -613,7 +621,8 @@ void ApplicationCacheStorage::openDatabase(bool createIfDoesNotExist) executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheEntries (cache INTEGER NOT NULL ON CONFLICT FAIL, type INTEGER, resource INTEGER NOT NULL)"); executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheResources (id INTEGER PRIMARY KEY AUTOINCREMENT, url TEXT NOT NULL ON CONFLICT FAIL, " "statusCode INTEGER NOT NULL, responseURL TEXT NOT NULL, mimeType TEXT, textEncodingName TEXT, headers TEXT, data INTEGER NOT NULL ON CONFLICT FAIL)"); - executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheResourceData (id INTEGER PRIMARY KEY AUTOINCREMENT, data BLOB)"); + executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheResourceData (id INTEGER PRIMARY KEY AUTOINCREMENT, data BLOB, path TEXT)"); + executeSQLCommand("CREATE TABLE IF NOT EXISTS DeletedCacheResources (id INTEGER PRIMARY KEY AUTOINCREMENT, path TEXT)"); executeSQLCommand("CREATE TABLE IF NOT EXISTS Origins (origin TEXT UNIQUE ON CONFLICT IGNORE, quota INTEGER NOT NULL ON CONFLICT FAIL)"); // When a cache is deleted, all its entries and its whitelist should be deleted. @@ -636,6 +645,15 @@ void ApplicationCacheStorage::openDatabase(bool createIfDoesNotExist) " FOR EACH ROW BEGIN" " DELETE FROM CacheResourceData WHERE id = OLD.data;" " END"); + + // When a cache resource is deleted, if it contains a non-empty path, that path should + // be added to the DeletedCacheResources table so the flat file at that path can + // be deleted at a later time. + executeSQLCommand("CREATE TRIGGER IF NOT EXISTS CacheResourceDataDeleted AFTER DELETE ON CacheResourceData" + " FOR EACH ROW" + " WHEN OLD.path NOT NULL BEGIN" + " INSERT INTO DeletedCacheResources (path) values (OLD.path);" + " END"); } bool ApplicationCacheStorage::executeStatement(SQLiteStatement& statement) @@ -767,15 +785,43 @@ bool ApplicationCacheStorage::store(ApplicationCacheResource* resource, unsigned return false; // First, insert the data - SQLiteStatement dataStatement(m_database, "INSERT INTO CacheResourceData (data) VALUES (?)"); + SQLiteStatement dataStatement(m_database, "INSERT INTO CacheResourceData (data, path) VALUES (?, ?)"); if (dataStatement.prepare() != SQLResultOk) return false; - if (resource->data()->size()) - dataStatement.bindBlob(1, resource->data()->data(), resource->data()->size()); + + String fullPath; + if (!resource->path().isEmpty()) + dataStatement.bindText(2, pathGetFileName(resource->path())); + else if (shouldStoreResourceAsFlatFile(resource)) { + // First, check to see if creating the flat file would violate the maximum total quota. We don't need + // to check the per-origin quota here, as it was already checked in storeNewestCache(). + if (m_database.totalSize() + flatFileAreaSize() + resource->data()->size() > m_maximumSize) { + m_isMaximumSizeReached = true; + return false; + } + + String flatFileDirectory = pathByAppendingComponent(m_cacheDirectory, flatFileSubdirectory); + makeAllDirectories(flatFileDirectory); + String path; + if (!writeDataToUniqueFileInDirectory(resource->data(), flatFileDirectory, path)) + return false; + + fullPath = pathByAppendingComponent(flatFileDirectory, path); + resource->setPath(fullPath); + dataStatement.bindText(2, path); + } else { + if (resource->data()->size()) + dataStatement.bindBlob(1, resource->data()->data(), resource->data()->size()); + } - if (!dataStatement.executeCommand()) + if (!dataStatement.executeCommand()) { + // Clean up the file which we may have written to: + if (!fullPath.isEmpty()) + deleteFile(fullPath); + return false; + } unsigned dataId = static_cast<unsigned>(m_database.lastInsertRowID()); @@ -826,6 +872,12 @@ bool ApplicationCacheStorage::store(ApplicationCacheResource* resource, unsigned if (!executeStatement(entryStatement)) return false; + // Did we successfully write the resource data to a file? If so, + // release the resource's data and free up a potentially large amount + // of memory: + if (!fullPath.isEmpty()) + resource->data()->clear(); + resource->setStorageID(resourceId); return true; } @@ -856,7 +908,7 @@ bool ApplicationCacheStorage::store(ApplicationCacheResource* resource, Applicat return false; m_isMaximumSizeReached = false; - m_database.setMaximumSize(m_maximumSize); + m_database.setMaximumSize(m_maximumSize - flatFileAreaSize()); SQLiteTransaction storeResourceTransaction(m_database); storeResourceTransaction.begin(); @@ -903,7 +955,7 @@ bool ApplicationCacheStorage::storeNewestCache(ApplicationCacheGroup* group, App return false; m_isMaximumSizeReached = false; - m_database.setMaximumSize(m_maximumSize); + m_database.setMaximumSize(m_maximumSize - flatFileAreaSize()); SQLiteTransaction storeCacheTransaction(m_database); @@ -1003,7 +1055,7 @@ static inline void parseHeaders(const String& headers, ResourceResponse& respons PassRefPtr<ApplicationCache> ApplicationCacheStorage::loadCache(unsigned storageID) { SQLiteStatement cacheStatement(m_database, - "SELECT url, type, mimeType, textEncodingName, headers, CacheResourceData.data FROM CacheEntries INNER JOIN CacheResources ON CacheEntries.resource=CacheResources.id " + "SELECT url, 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=?"); if (cacheStatement.prepare() != SQLResultOk) { LOG_ERROR("Could not prepare cache statement, error \"%s\"", m_database.lastErrorMsg()); @@ -1013,7 +1065,9 @@ PassRefPtr<ApplicationCache> ApplicationCacheStorage::loadCache(unsigned storage cacheStatement.bindInt64(1, storageID); RefPtr<ApplicationCache> cache = ApplicationCache::create(); - + + String flatFileDirectory = pathByAppendingComponent(m_cacheDirectory, flatFileSubdirectory); + int result; while ((result = cacheStatement.step()) == SQLResultRow) { KURL url(ParsedURLString, cacheStatement.getColumnText(0)); @@ -1025,15 +1079,24 @@ PassRefPtr<ApplicationCache> ApplicationCacheStorage::loadCache(unsigned storage RefPtr<SharedBuffer> data = SharedBuffer::adoptVector(blob); + String path = cacheStatement.getColumnText(6); + long long size = 0; + if (path.isEmpty()) + size = data->size(); + else { + path = pathByAppendingComponent(flatFileDirectory, path); + getFileSize(path, size); + } + String mimeType = cacheStatement.getColumnText(2); String textEncodingName = cacheStatement.getColumnText(3); - ResourceResponse response(url, mimeType, data->size(), textEncodingName, ""); + ResourceResponse response(url, mimeType, size, textEncodingName, ""); String headers = cacheStatement.getColumnText(4); parseHeaders(headers, response); - RefPtr<ApplicationCacheResource> resource = ApplicationCacheResource::create(url, response, type, data.release()); + RefPtr<ApplicationCacheResource> resource = ApplicationCacheResource::create(url, response, type, data.release(), path); if (type & ApplicationCacheResource::Manifest) cache->setManifestResource(resource.release()); @@ -1127,6 +1190,8 @@ void ApplicationCacheStorage::remove(ApplicationCache* cache) cache->group()->clearStorageID(); } + + checkForDeletedResources(); } void ApplicationCacheStorage::empty() @@ -1147,7 +1212,51 @@ void ApplicationCacheStorage::empty() CacheGroupMap::const_iterator end = m_cachesInMemory.end(); for (CacheGroupMap::const_iterator it = m_cachesInMemory.begin(); it != end; ++it) it->second->clearStorageID(); -} + + checkForDeletedResources(); +} + +void ApplicationCacheStorage::deleteTables() +{ + empty(); + m_database.clearAllTables(); +} + +bool ApplicationCacheStorage::shouldStoreResourceAsFlatFile(ApplicationCacheResource* resource) +{ + return resource->response().mimeType().startsWith("audio/", false) + || resource->response().mimeType().startsWith("video/", false); +} + +bool ApplicationCacheStorage::writeDataToUniqueFileInDirectory(SharedBuffer* data, const String& directory, String& path) +{ + String fullPath; + + do { + path = encodeForFileName(createCanonicalUUIDString()); + // Guard against the above function being called on a platform which does not implement + // createCanonicalUUIDString(). + ASSERT(!path.isEmpty()); + if (path.isEmpty()) + return false; + + fullPath = pathByAppendingComponent(directory, path); + } while (directoryName(fullPath) != directory || fileExists(fullPath)); + + PlatformFileHandle handle = openFile(fullPath, OpenForWrite); + if (!handle) + return false; + + int64_t writtenBytes = writeToFile(handle, data->data(), data->size()); + closeFile(handle); + + if (writtenBytes != static_cast<int64_t>(data->size())) { + deleteFile(fullPath); + return false; + } + + return true; +} bool ApplicationCacheStorage::storeCopyOfCache(const String& cacheDirectory, ApplicationCacheHost* cacheHost) { @@ -1166,7 +1275,7 @@ bool ApplicationCacheStorage::storeCopyOfCache(const String& cacheDirectory, App for (ApplicationCache::ResourceMap::const_iterator it = cache->begin(); it != end; ++it) { ApplicationCacheResource* resource = it->second.get(); - RefPtr<ApplicationCacheResource> resourceCopy = ApplicationCacheResource::create(resource->url(), resource->response(), resource->type(), resource->data()); + RefPtr<ApplicationCacheResource> resourceCopy = ApplicationCacheResource::create(resource->url(), resource->response(), resource->type(), resource->data(), resource->path()); cacheCopy->addResource(resourceCopy.release()); } @@ -1274,6 +1383,9 @@ bool ApplicationCacheStorage::deleteCacheGroup(const String& manifestURL) } deleteTransaction.commit(); + + checkForDeletedResources(); + return true; } @@ -1291,25 +1403,73 @@ void ApplicationCacheStorage::checkForMaxSizeReached() if (m_database.lastError() == SQLResultFull) m_isMaximumSizeReached = true; } - -void ApplicationCacheStorage::getOriginsWithCache(HashSet<RefPtr<SecurityOrigin>, SecurityOriginHash>& origins) + +void ApplicationCacheStorage::checkForDeletedResources() { - Vector<KURL> urls; - if (!manifestURLs(&urls)) { - LOG_ERROR("Failed to retrieve ApplicationCache manifest URLs"); + openDatabase(false); + if (!m_database.isOpen()) return; + + // Select only the paths in DeletedCacheResources that do not also appear in CacheResourceData: + SQLiteStatement selectPaths(m_database, "SELECT DeletedCacheResources.path " + "FROM DeletedCacheResources " + "LEFT JOIN CacheResourceData " + "ON DeletedCacheResources.path = CacheResourceData.path " + "WHERE (SELECT DeletedCacheResources.path == CacheResourceData.path) IS NULL"); + + if (selectPaths.prepare() != SQLResultOk) + return; + + if (selectPaths.step() != SQLResultRow) + return; + + do { + String path = selectPaths.getColumnText(0); + if (path.isEmpty()) + continue; + + String flatFileDirectory = pathByAppendingComponent(m_cacheDirectory, flatFileSubdirectory); + String fullPath = pathByAppendingComponent(flatFileDirectory, path); + + // Don't exit the flatFileDirectory! This should only happen if the "path" entry contains a directory + // component, but protect against it regardless. + if (directoryName(fullPath) != flatFileDirectory) + continue; + + deleteFile(fullPath); + } while (selectPaths.step() == SQLResultRow); + + executeSQLCommand("DELETE FROM DeletedCacheResources"); +} + +long long ApplicationCacheStorage::flatFileAreaSize() +{ + openDatabase(false); + if (!m_database.isOpen()) + return 0; + + SQLiteStatement selectPaths(m_database, "SELECT path FROM CacheResourceData WHERE path NOT NULL"); + + if (selectPaths.prepare() != SQLResultOk) { + LOG_ERROR("Could not load flat file cache resource data, error \"%s\"", m_database.lastErrorMsg()); + return 0; } - // Multiple manifest URLs might share the same SecurityOrigin, so we might be creating extra, wasted origins here. - // The current schema doesn't allow for a more efficient way of building this list. - size_t count = urls.size(); - for (size_t i = 0; i < count; ++i) { - RefPtr<SecurityOrigin> origin = SecurityOrigin::create(urls[i]); - origins.add(origin); + long long totalSize = 0; + String flatFileDirectory = pathByAppendingComponent(m_cacheDirectory, flatFileSubdirectory); + while (selectPaths.step() == SQLResultRow) { + String path = selectPaths.getColumnText(0); + String fullPath = pathByAppendingComponent(flatFileDirectory, path); + long long pathSize = 0; + if (!getFileSize(fullPath, pathSize)) + continue; + totalSize += pathSize; } + + return totalSize; } -void ApplicationCacheStorage::deleteEntriesForOrigin(SecurityOrigin* origin) +void ApplicationCacheStorage::getOriginsWithCache(HashSet<RefPtr<SecurityOrigin>, SecurityOriginHash>& origins) { Vector<KURL> urls; if (!manifestURLs(&urls)) { @@ -1318,12 +1478,11 @@ void ApplicationCacheStorage::deleteEntriesForOrigin(SecurityOrigin* origin) } // Multiple manifest URLs might share the same SecurityOrigin, so we might be creating extra, wasted origins here. - // The current schema doesn't allow for a more efficient way of deleting by origin. + // The current schema doesn't allow for a more efficient way of building this list. size_t count = urls.size(); for (size_t i = 0; i < count; ++i) { - RefPtr<SecurityOrigin> manifestOrigin = SecurityOrigin::create(urls[i]); - if (manifestOrigin->isSameSchemeHostPort(origin)) - deleteCacheGroup(urls[i]); + RefPtr<SecurityOrigin> origin = SecurityOrigin::create(urls[i]); + origins.add(origin); } } diff --git a/Source/WebCore/loader/appcache/ApplicationCacheStorage.h b/Source/WebCore/loader/appcache/ApplicationCacheStorage.h index f283670..3136b52 100644 --- a/Source/WebCore/loader/appcache/ApplicationCacheStorage.h +++ b/Source/WebCore/loader/appcache/ApplicationCacheStorage.h @@ -74,6 +74,7 @@ public: ApplicationCacheGroup* fallbackCacheGroupForURL(const KURL&); // Cache that has a fallback entry to load a main resource from if normal loading fails. ApplicationCacheGroup* findOrCreateCacheGroup(const KURL& manifestURL); + ApplicationCacheGroup* findInMemoryCacheGroup(const KURL& manifestURL) const; void cacheGroupDestroyed(ApplicationCacheGroup*); void cacheGroupMadeObsolete(ApplicationCacheGroup*); @@ -95,7 +96,6 @@ public: void vacuumDatabaseFile(); void getOriginsWithCache(HashSet<RefPtr<SecurityOrigin>, SecurityOriginHash>&); - void deleteEntriesForOrigin(SecurityOrigin*); void deleteAllEntries(); static int64_t unknownQuota() { return -1; } @@ -113,6 +113,9 @@ private: bool store(ApplicationCacheResource*, unsigned cacheStorageID); bool ensureOriginRecord(const SecurityOrigin*); + bool shouldStoreResourceAsFlatFile(ApplicationCacheResource*); + void deleteTables(); + bool writeDataToUniqueFileInDirectory(SharedBuffer*, const String& directory, String& outFilename); void loadManifestHostHashes(); @@ -124,6 +127,8 @@ private: bool executeSQLCommand(const String&); void checkForMaxSizeReached(); + void checkForDeletedResources(); + long long flatFileAreaSize(); String m_cacheDirectory; String m_cacheFile; diff --git a/Source/WebCore/loader/archive/cf/LegacyWebArchive.cpp b/Source/WebCore/loader/archive/cf/LegacyWebArchive.cpp index 7979423..6e0a1eb 100644 --- a/Source/WebCore/loader/archive/cf/LegacyWebArchive.cpp +++ b/Source/WebCore/loader/archive/cf/LegacyWebArchive.cpp @@ -546,9 +546,9 @@ PassRefPtr<LegacyWebArchive> LegacyWebArchive::create(const String& markupString // Add favicon if one exists for this page, if we are archiving the entire page. if (nodesSize && nodes[0]->isDocumentNode() && iconDatabase().isEnabled()) { - const String& iconURL = iconDatabase().iconURLForPageURL(responseURL); - if (!iconURL.isEmpty() && iconDatabase().iconDataKnownForIconURL(iconURL)) { - if (Image* iconImage = iconDatabase().iconForPageURL(responseURL, IntSize(16, 16))) { + const String& iconURL = iconDatabase().synchronousIconURLForPageURL(responseURL); + if (!iconURL.isEmpty() && iconDatabase().synchronousIconDataKnownForIconURL(iconURL)) { + if (Image* iconImage = iconDatabase().synchronousIconForPageURL(responseURL, IntSize(16, 16))) { if (RefPtr<ArchiveResource> resource = ArchiveResource::create(iconImage->data(), KURL(ParsedURLString, iconURL), "image/x-icon", "", "")) subresources.append(resource.release()); } diff --git a/Source/WebCore/loader/cache/CachedFont.cpp b/Source/WebCore/loader/cache/CachedFont.cpp index 19eb3ba..ea2ee14 100644 --- a/Source/WebCore/loader/cache/CachedFont.cpp +++ b/Source/WebCore/loader/cache/CachedFont.cpp @@ -117,7 +117,7 @@ bool CachedFont::ensureCustomFontData() return m_fontData; } -FontPlatformData CachedFont::platformDataFromCustomData(float size, bool bold, bool italic, FontOrientation orientation, FontWidthVariant widthVariant, FontRenderingMode renderingMode) +FontPlatformData CachedFont::platformDataFromCustomData(float size, bool bold, bool italic, FontOrientation orientation, TextOrientation textOrientation, FontWidthVariant widthVariant, FontRenderingMode renderingMode) { #if ENABLE(SVG_FONTS) if (m_externalSVGDocument) @@ -125,7 +125,7 @@ FontPlatformData CachedFont::platformDataFromCustomData(float size, bool bold, b #endif #ifdef STORE_FONT_CUSTOM_PLATFORM_DATA ASSERT(m_fontData); - return m_fontData->fontPlatformData(static_cast<int>(size), bold, italic, orientation, widthVariant, renderingMode); + return m_fontData->fontPlatformData(static_cast<int>(size), bold, italic, orientation, textOrientation, widthVariant, renderingMode); #else return FontPlatformData(); #endif diff --git a/Source/WebCore/loader/cache/CachedFont.h b/Source/WebCore/loader/cache/CachedFont.h index cdc32ba..d677f7b 100644 --- a/Source/WebCore/loader/cache/CachedFont.h +++ b/Source/WebCore/loader/cache/CachedFont.h @@ -30,6 +30,7 @@ #include "FontOrientation.h" #include "FontRenderingMode.h" #include "FontWidthVariant.h" +#include "TextOrientation.h" #include <wtf/Vector.h> #if ENABLE(SVG_FONTS) @@ -64,7 +65,7 @@ public: void beginLoadIfNeeded(CachedResourceLoader* dl); bool ensureCustomFontData(); - FontPlatformData platformDataFromCustomData(float size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode); + FontPlatformData platformDataFromCustomData(float size, bool bold, bool italic, FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode); #if ENABLE(SVG_FONTS) bool isSVGFont() const { return m_isSVGFont; } diff --git a/Source/WebCore/loader/cache/CachedImage.cpp b/Source/WebCore/loader/cache/CachedImage.cpp index b309ae6..cc49415 100644 --- a/Source/WebCore/loader/cache/CachedImage.cpp +++ b/Source/WebCore/loader/cache/CachedImage.cpp @@ -325,16 +325,6 @@ void CachedImage::error(CachedResource::Status status) checkNotify(); } -void CachedImage::checkNotify() -{ - if (isLoading()) - return; - - CachedResourceClientWalker w(m_clients); - while (CachedResourceClient* c = w.next()) - c->notifyFinished(this); -} - void CachedImage::destroyDecodedData() { bool canDeleteImage = !m_image || (m_image->hasOneRef() && m_image->isBitmapImage()); diff --git a/Source/WebCore/loader/cache/CachedImage.h b/Source/WebCore/loader/cache/CachedImage.h index 3242409..42c7814 100644 --- a/Source/WebCore/loader/cache/CachedImage.h +++ b/Source/WebCore/loader/cache/CachedImage.h @@ -71,8 +71,6 @@ public: // For compatibility, images keep loading even if there are HTTP errors. virtual bool shouldIgnoreHTTPStatusCodeErrors() const { return true; } - void checkNotify(); - virtual bool isImage() const { return true; } void clear(); diff --git a/Source/WebCore/loader/cache/CachedResource.cpp b/Source/WebCore/loader/cache/CachedResource.cpp index 0f9ff45..9413472 100644 --- a/Source/WebCore/loader/cache/CachedResource.cpp +++ b/Source/WebCore/loader/cache/CachedResource.cpp @@ -93,8 +93,8 @@ CachedResource::CachedResource(const String& url, Type type) , m_loading(false) , m_type(type) , m_status(Pending) - , m_deleted(false) #ifndef NDEBUG + , m_deleted(false) , m_lruIndex(0) #endif , m_nextInAllResourcesList(0) @@ -118,13 +118,8 @@ CachedResource::~CachedResource() ASSERT(!m_deleted); ASSERT(url().isNull() || memoryCache()->resourceForURL(KURL(ParsedURLString, url())) != this); - if (m_deleted) { - // FIXME: Remove when http://webkit.org/b/53045 is fixed. - CRASH(); - } - - m_deleted = true; #ifndef NDEBUG + m_deleted = true; cachedResourceLeakCounter.decrement(); #endif @@ -139,15 +134,33 @@ void CachedResource::load(CachedResourceLoader* cachedResourceLoader, bool incre m_loading = true; } +void CachedResource::checkNotify() +{ + if (isLoading()) + return; + + CachedResourceClientWalker w(m_clients); + while (CachedResourceClient* c = w.next()) + c->notifyFinished(this); +} + void CachedResource::data(PassRefPtr<SharedBuffer>, bool allDataReceived) { if (!allDataReceived) return; setLoading(false); - CachedResourceClientWalker w(m_clients); - while (CachedResourceClient* c = w.next()) - c->notifyFinished(this); + checkNotify(); +} + +void CachedResource::error(CachedResource::Status status) +{ + setStatus(status); + ASSERT(errorOccurred()); + m_data.clear(); + + setLoading(false); + checkNotify(); } void CachedResource::finish() diff --git a/Source/WebCore/loader/cache/CachedResource.h b/Source/WebCore/loader/cache/CachedResource.h index 3379f8c..16920a5 100644 --- a/Source/WebCore/loader/cache/CachedResource.h +++ b/Source/WebCore/loader/cache/CachedResource.h @@ -86,7 +86,7 @@ public: virtual void setEncoding(const String&) { } virtual String encoding() const { return String(); } virtual void data(PassRefPtr<SharedBuffer> data, bool allDataReceived); - virtual void error(CachedResource::Status) { } + virtual void error(CachedResource::Status); virtual bool shouldIgnoreHTTPStatusCodeErrors() const { return false; } @@ -217,6 +217,8 @@ public: void updateResponseAfterRevalidation(const ResourceResponse& validatingResponse); protected: + void checkNotify(); + void setEncodedSize(unsigned); void setDecodedSize(unsigned); void didAccessDecodedData(double timeStamp); @@ -266,9 +268,8 @@ private: unsigned m_type : 3; // Type unsigned m_status : 3; // Status - // FIXME: Move m_deleted back inside NDEBUG when http://webkit.org/b/53045 is fixed. - bool m_deleted; #ifndef NDEBUG + bool m_deleted; unsigned m_lruIndex; #endif diff --git a/Source/WebCore/loader/cache/CachedResourceLoader.cpp b/Source/WebCore/loader/cache/CachedResourceLoader.cpp index 56715c6..3b6a0b2 100644 --- a/Source/WebCore/loader/cache/CachedResourceLoader.cpp +++ b/Source/WebCore/loader/cache/CachedResourceLoader.cpp @@ -34,6 +34,7 @@ #include "CachedScript.h" #include "CachedXSLStyleSheet.h" #include "Console.h" +#include "ContentSecurityPolicy.h" #include "DOMWindow.h" #include "Document.h" #include "Frame.h" @@ -41,7 +42,6 @@ #include "FrameLoaderClient.h" #include "HTMLElement.h" #include "Logging.h" -#include "NestingLevelIncrementer.h" #include "MemoryCache.h" #include "PingLoader.h" #include "ResourceLoadScheduler.h" @@ -85,21 +85,18 @@ CachedResourceLoader::CachedResourceLoader(Document* document) , m_autoLoadImages(true) , m_loadFinishing(false) , m_allowStaleResources(false) +<<<<<<< HEAD #ifdef ANDROID_BLOCK_NETWORK_IMAGE , m_blockNetworkImage(false) #endif , m_isInMethod(0) +======= +>>>>>>> webkit.org at r82507 { } CachedResourceLoader::~CachedResourceLoader() { - // Try to catch https://bugs.webkit.org/show_bug.cgi?id=54486 - // Crashes under CachedResourceLoader::revalidateResource - // FIXME: Remove this and the related code when it has served its purpose. - if (m_isInMethod) - CRASH(); - m_document = 0; cancelRequests(); @@ -131,7 +128,6 @@ Frame* CachedResourceLoader::frame() const CachedImage* CachedResourceLoader::requestImage(const String& url) { - NestingLevelIncrementer debugIncrementer(m_isInMethod); if (Frame* f = frame()) { Settings* settings = f->settings(); if (!f->loader()->client()->allowImages(!settings || settings->areImagesEnabled())) @@ -169,7 +165,6 @@ CachedCSSStyleSheet* CachedResourceLoader::requestCSSStyleSheet(const String& ur CachedCSSStyleSheet* CachedResourceLoader::requestUserCSSStyleSheet(const String& requestURL, const String& charset) { - NestingLevelIncrementer debugIncrementer(m_isInMethod); KURL url = MemoryCache::removeFragmentIdentifierIfNeeded(KURL(KURL(), requestURL)); if (CachedResource* existing = memoryCache()->resourceForURL(url)) { @@ -235,9 +230,6 @@ bool CachedResourceLoader::canRequest(CachedResource::Type type, const KURL& url } break; #endif - default: - ASSERT_NOT_REACHED(); - break; } // Given that the load is allowed by the same-origin policy, we should @@ -271,17 +263,17 @@ bool CachedResourceLoader::canRequest(CachedResource::Type type, const KURL& url // Prefetch cannot affect the current document. break; #endif - default: - ASSERT_NOT_REACHED(); - break; } // FIXME: Consider letting the embedder block mixed content loads. + + if (type == CachedResource::Script && !m_document->contentSecurityPolicy()->allowScriptFromSource(url)) + return false; + return true; } CachedResource* CachedResourceLoader::requestResource(CachedResource::Type type, const String& resourceURL, const String& charset, ResourceLoadPriority priority, bool forPreload) { - NestingLevelIncrementer debugIncrementer(m_isInMethod); KURL url = m_document->completeURL(resourceURL); LOG(ResourceLoading, "CachedResourceLoader::requestResource '%s', charset '%s', priority=%d, forPreload=%u", url.string().latin1().data(), charset.latin1().data(), priority, forPreload); @@ -348,7 +340,8 @@ CachedResource* CachedResourceLoader::revalidateResource(CachedResource* resourc ASSERT(resource->canUseCacheValidator()); ASSERT(!resource->resourceToRevalidate()); - const String& url = resource->url(); + // Copy the URL out of the resource to be revalidated in case it gets deleted by the remove() call below. + String url = resource->url(); CachedResource* newResource = createResource(resource->type(), KURL(ParsedURLString, url), resource->encoding()); LOG(ResourceLoading, "Resource %p created to revalidate %p", newResource, resource); @@ -489,7 +482,6 @@ void CachedResourceLoader::printAccessDeniedMessage(const KURL& url) const void CachedResourceLoader::setAutoLoadImages(bool enable) { - NestingLevelIncrementer debugIncrementer(m_isInMethod); if (enable == m_autoLoadImages) return; @@ -566,7 +558,6 @@ void CachedResourceLoader::removeCachedResource(CachedResource* resource) const void CachedResourceLoader::load(CachedResource* resource, bool incremental, SecurityCheckPolicy securityCheck, bool sendResourceLoadCallbacks) { - NestingLevelIncrementer debugIncrementer(m_isInMethod); incrementRequestCount(resource); RefPtr<CachedResourceRequest> request = CachedResourceRequest::load(this, resource, incremental, securityCheck, sendResourceLoadCallbacks); @@ -576,7 +567,6 @@ void CachedResourceLoader::load(CachedResource* resource, bool incremental, Secu void CachedResourceLoader::loadDone(CachedResourceRequest* request) { - NestingLevelIncrementer debugIncrementer(m_isInMethod); m_loadFinishing = false; RefPtr<CachedResourceRequest> protect(request); if (request) @@ -653,7 +643,6 @@ int CachedResourceLoader::requestCount() void CachedResourceLoader::preload(CachedResource::Type type, const String& url, const String& charset, bool referencedFromBody) { - NestingLevelIncrementer debugIncrementer(m_isInMethod); bool hasRendering = m_document->body() && m_document->body()->renderer(); if (!hasRendering && (referencedFromBody || type == CachedResource::ImageResource)) { // Don't preload images or body resources before we have something to draw. This prevents @@ -680,7 +669,6 @@ void CachedResourceLoader::checkForPendingPreloads() void CachedResourceLoader::requestPreload(CachedResource::Type type, const String& url, const String& charset) { - NestingLevelIncrementer debugIncrementer(m_isInMethod); String encoding; if (type == CachedResource::Script || type == CachedResource::CSSStyleSheet) encoding = charset.isEmpty() ? m_document->charset() : charset; diff --git a/Source/WebCore/loader/cache/CachedResourceLoader.h b/Source/WebCore/loader/cache/CachedResourceLoader.h index 0302010..a68ebd3 100644 --- a/Source/WebCore/loader/cache/CachedResourceLoader.h +++ b/Source/WebCore/loader/cache/CachedResourceLoader.h @@ -153,12 +153,15 @@ private: bool m_autoLoadImages : 1; bool m_loadFinishing : 1; bool m_allowStaleResources : 1; +<<<<<<< HEAD #ifdef ANDROID_BLOCK_NETWORK_IMAGE bool m_blockNetworkImage : 1; #endif // FIME: For debugging, remove. unsigned m_isInMethod; +======= +>>>>>>> webkit.org at r82507 }; } diff --git a/Source/WebCore/loader/cache/CachedScript.cpp b/Source/WebCore/loader/cache/CachedScript.cpp index bfd39c5..e1a8a32 100644 --- a/Source/WebCore/loader/cache/CachedScript.cpp +++ b/Source/WebCore/loader/cache/CachedScript.cpp @@ -88,6 +88,8 @@ const String& CachedScript::script() m_script += m_decoder->flush(); setDecodedSize(m_script.length() * sizeof(UChar)); } + m_decodedDataDeletionTimer.startOneShot(0); + return m_script; } @@ -102,16 +104,6 @@ void CachedScript::data(PassRefPtr<SharedBuffer> data, bool allDataReceived) checkNotify(); } -void CachedScript::checkNotify() -{ - if (isLoading()) - return; - - CachedResourceClientWalker w(m_clients); - while (CachedResourceClient* c = w.next()) - c->notifyFinished(this); -} - void CachedScript::error(CachedResource::Status status) { setStatus(status); @@ -125,7 +117,7 @@ void CachedScript::destroyDecodedData() m_script = String(); unsigned extraSize = 0; #if USE(JSC) - if (m_sourceProviderCache) + if (m_sourceProviderCache && m_clients.isEmpty()) m_sourceProviderCache->clear(); extraSize = m_sourceProviderCache ? m_sourceProviderCache->byteSize() : 0; diff --git a/Source/WebCore/loader/cache/CachedScript.h b/Source/WebCore/loader/cache/CachedScript.h index 85c3805..a4ea453 100644 --- a/Source/WebCore/loader/cache/CachedScript.h +++ b/Source/WebCore/loader/cache/CachedScript.h @@ -55,8 +55,6 @@ namespace WebCore { virtual void data(PassRefPtr<SharedBuffer> data, bool allDataReceived); virtual void error(Status); - void checkNotify(); - virtual void destroyDecodedData(); #if USE(JSC) // Allows JSC to cache additional information about the source. diff --git a/Source/WebCore/loader/cf/SubresourceLoaderCF.cpp b/Source/WebCore/loader/cf/SubresourceLoaderCF.cpp new file mode 100644 index 0000000..f6ce93f --- /dev/null +++ b/Source/WebCore/loader/cf/SubresourceLoaderCF.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "SubresourceLoader.h" + +#include "SubresourceLoaderClient.h" + +namespace WebCore { + +#if HAVE(CFNETWORK_DATA_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. + RefPtr<SubresourceLoader> protect(this); + + ResourceLoader::didReceiveDataArray(dataArray); + + // A subresource loader does not load multipart sections progressively. + // So don't deliver any data to the loader yet. + if (!m_loadingMultipartContent && m_client) { + CFIndex arrayCount = CFArrayGetCount(dataArray); + for (CFIndex i = 0; i < arrayCount; ++i) { + CFDataRef data = reinterpret_cast<CFDataRef>(CFArrayGetValueAtIndex(dataArray, i)); + m_client->didReceiveData(this, reinterpret_cast<const char *>(CFDataGetBytePtr(data)), static_cast<int>(CFDataGetLength(data))); + } + } +} +#endif + +} diff --git a/Source/WebCore/loader/icon/IconDatabase.cpp b/Source/WebCore/loader/icon/IconDatabase.cpp index 26f3bb7..e5578e0 100644 --- a/Source/WebCore/loader/icon/IconDatabase.cpp +++ b/Source/WebCore/loader/icon/IconDatabase.cpp @@ -58,7 +58,6 @@ namespace WebCore { -static IconDatabase* sharedIconDatabase = 0; static int databaseCleanupCounter = 0; // This version number is in the DB and marks the current generation of the schema @@ -85,21 +84,22 @@ static String urlForLogging(const String& url) } #endif +class DefaultIconDatabaseClient : public IconDatabaseClient { +public: + virtual bool performImport() { return true; } + virtual void didImportIconURLForPageURL(const String&) { } + virtual void didImportIconDataForPageURL(const String&) { } + virtual void didChangeIconForPageURL(const String&) { } + virtual void didRemoveAllIcons() { } + virtual void didFinishURLImport() { } +}; + static IconDatabaseClient* defaultClient() { - static IconDatabaseClient* defaultClient = new IconDatabaseClient(); + static IconDatabaseClient* defaultClient = new DefaultIconDatabaseClient(); return defaultClient; } -IconDatabase& iconDatabase() -{ - if (!sharedIconDatabase) { - ScriptController::initializeThreading(); - sharedIconDatabase = new IconDatabase; - } - return *sharedIconDatabase; -} - // ************************ // *** Main Thread Only *** // ************************ @@ -117,7 +117,7 @@ void IconDatabase::setClient(IconDatabaseClient* client) m_client = client; } -bool IconDatabase::open(const String& databasePath) +bool IconDatabase::open(const String& directory, const String& filename) { ASSERT_NOT_SYNC_THREAD(); @@ -129,10 +129,10 @@ bool IconDatabase::open(const String& databasePath) return false; } - m_databaseDirectory = databasePath.crossThreadString(); + m_databaseDirectory = directory.crossThreadString(); // Formulate the full path for the database file - m_completeDatabasePath = pathByAppendingComponent(m_databaseDirectory, defaultDatabaseFilename()); + m_completeDatabasePath = pathByAppendingComponent(m_databaseDirectory, filename); // Lock here as well as first thing in the thread so the thread doesn't actually commence until the createThread() call // completes and m_syncThreadRunning is properly set @@ -217,7 +217,7 @@ void IconDatabase::removeAllIcons() wakeSyncThread(); } -Image* IconDatabase::iconForPageURL(const String& pageURLOriginal, const IntSize& size) +Image* IconDatabase::synchronousIconForPageURL(const String& pageURLOriginal, const IntSize& size) { ASSERT_NOT_SYNC_THREAD(); @@ -301,10 +301,10 @@ void IconDatabase::readIconForPageURLFromDisk(const String& pageURL) // The effect of asking for an Icon for a pageURL automatically queues it to be read from disk // if it hasn't already been set in memory. The special IntSize (0, 0) is a special way of telling // that method "I don't care about the actual Image, i just want you to make sure you're getting it from disk. - iconForPageURL(pageURL, IntSize(0,0)); + synchronousIconForPageURL(pageURL, IntSize(0, 0)); } -String IconDatabase::iconURLForPageURL(const String& pageURLOriginal) +String IconDatabase::synchronousIconURLForPageURL(const String& pageURLOriginal) { ASSERT_NOT_SYNC_THREAD(); @@ -565,7 +565,7 @@ void IconDatabase::setIconDataForIconURL(PassRefPtr<SharedBuffer> dataOriginal, for (unsigned i = 0; i < pageURLs.size(); ++i) { LOG(IconDatabase, "Dispatching notification that retaining pageURL %s has a new icon", urlForLogging(pageURLs[i]).ascii().data()); - m_client->dispatchDidAddIconForPageURL(pageURLs[i]); + m_client->didChangeIconForPageURL(pageURLs[i]); pool.cycle(); } @@ -637,11 +637,11 @@ void IconDatabase::setIconURLForPageURL(const String& iconURLOriginal, const Str LOG(IconDatabase, "Dispatching notification that we changed an icon mapping for url %s", urlForLogging(pageURL).ascii().data()); AutodrainedPool pool; - m_client->dispatchDidAddIconForPageURL(pageURL); + m_client->didChangeIconForPageURL(pageURL); } } -IconLoadDecision IconDatabase::loadDecisionForIconURL(const String& iconURL, DocumentLoader* notificationDocumentLoader) +IconLoadDecision IconDatabase::synchronousLoadDecisionForIconURL(const String& iconURL, DocumentLoader* notificationDocumentLoader) { ASSERT_NOT_SYNC_THREAD(); @@ -667,12 +667,13 @@ IconLoadDecision IconDatabase::loadDecisionForIconURL(const String& iconURL, Doc // Otherwise - since we refuse to perform I/O on the main thread to find out for sure - we return the answer that says // "You might be asked to load this later, so flag that" LOG(IconDatabase, "Don't know if we should load %s or not - adding %p to the set of document loaders waiting on a decision", iconURL.ascii().data(), notificationDocumentLoader); - m_loadersPendingDecision.add(notificationDocumentLoader); + if (notificationDocumentLoader) + m_loadersPendingDecision.add(notificationDocumentLoader); return IconLoadUnknown; } -bool IconDatabase::iconDataKnownForIconURL(const String& iconURL) +bool IconDatabase::synchronousIconDataKnownForIconURL(const String& iconURL) { ASSERT_NOT_SYNC_THREAD(); @@ -775,6 +776,7 @@ IconDatabase::IconDatabase() , m_imported(false) , m_isImportedSet(false) { + LOG(IconDatabase, "Creating IconDatabase %p", this); ASSERT(isMainThread()); } @@ -1257,7 +1259,7 @@ void IconDatabase::performURLImport() { MutexLocker locker(m_pendingReadingLock); if (m_pageURLsPendingImport.contains(pageURL)) { - m_client->dispatchDidAddIconForPageURL(pageURL); + dispatchDidImportIconURLForPageURLOnMainThread(pageURL); m_pageURLsPendingImport.remove(pageURL); pool.cycle(); @@ -1292,7 +1294,6 @@ void IconDatabase::performURLImport() // Loop through the urls pending import // Remove unretained ones if database cleanup is allowed // Keep a set of ones that are retained and pending notification - { MutexLocker locker(m_urlAndIconLock); @@ -1331,13 +1332,16 @@ void IconDatabase::performURLImport() // Now that we don't hold any locks, perform the actual notifications for (unsigned i = 0; i < urlsToNotify.size(); ++i) { LOG(IconDatabase, "Notifying icon info known for pageURL %s", urlsToNotify[i].ascii().data()); - m_client->dispatchDidAddIconForPageURL(urlsToNotify[i]); + dispatchDidImportIconURLForPageURLOnMainThread(urlsToNotify[i]); if (shouldStopThreadActivity()) return; pool.cycle(); } + // Notify the client that the URL import is complete in case it's managing its own pending notifications. + dispatchDidFinishURLImportOnMainThread(); + // Notify all DocumentLoaders that were waiting for an icon load decision on the main thread callOnMainThread(notifyPendingLoadDecisionsOnMainThread, this); } @@ -1540,7 +1544,7 @@ bool IconDatabase::readFromDatabase() HashSet<String>::iterator end = urlsToNotify.end(); for (unsigned iteration = 0; iter != end; ++iter, ++iteration) { LOG(IconDatabase, "Notifying icon received for pageURL %s", urlForLogging(*iter).ascii().data()); - m_client->dispatchDidAddIconForPageURL(*iter); + dispatchDidImportIconDataForPageURLOnMainThread(*iter); if (shouldStopThreadActivity()) return didAnyWork; @@ -1738,7 +1742,7 @@ void IconDatabase::removeAllIconsOnThread() createDatabaseTables(m_syncDB); LOG(IconDatabase, "Dispatching notification that we removed all icons"); - m_client->dispatchDidRemoveAllIcons(); + dispatchDidRemoveAllIconsOnMainThread(); } void IconDatabase::deleteAllPreparedStatements() @@ -2111,6 +2115,132 @@ void IconDatabase::setWasExcludedFromBackup() SQLiteStatement(m_syncDB, "INSERT INTO IconDatabaseInfo (key, value) VALUES ('ExcludedFromBackup', 1)").executeCommand(); } +class ClientWorkItem { +public: + ClientWorkItem(IconDatabaseClient* client) + : m_client(client) + { } + virtual void performWork() = 0; + virtual ~ClientWorkItem() { } + +protected: + IconDatabaseClient* m_client; +}; + +class ImportedIconURLForPageURLWorkItem : public ClientWorkItem { +public: + ImportedIconURLForPageURLWorkItem(IconDatabaseClient* client, const String& pageURL) + : ClientWorkItem(client) + , m_pageURL(new String(pageURL.threadsafeCopy())) + { } + + virtual ~ImportedIconURLForPageURLWorkItem() + { + delete m_pageURL; + } + + virtual void performWork() + { + ASSERT(m_client); + m_client->didImportIconURLForPageURL(*m_pageURL); + m_client = 0; + } + +private: + String* m_pageURL; +}; + +class ImportedIconDataForPageURLWorkItem : public ClientWorkItem { +public: + ImportedIconDataForPageURLWorkItem(IconDatabaseClient* client, const String& pageURL) + : ClientWorkItem(client) + , m_pageURL(new String(pageURL.threadsafeCopy())) + { } + + virtual ~ImportedIconDataForPageURLWorkItem() + { + delete m_pageURL; + } + + virtual void performWork() + { + ASSERT(m_client); + m_client->didImportIconDataForPageURL(*m_pageURL); + m_client = 0; + } + +private: + String* m_pageURL; +}; + +class RemovedAllIconsWorkItem : public ClientWorkItem { +public: + RemovedAllIconsWorkItem(IconDatabaseClient* client) + : ClientWorkItem(client) + { } + + virtual void performWork() + { + ASSERT(m_client); + m_client->didRemoveAllIcons(); + m_client = 0; + } +}; + +class FinishedURLImport : public ClientWorkItem { +public: + FinishedURLImport(IconDatabaseClient* client) + : ClientWorkItem(client) + { } + + virtual void performWork() + { + ASSERT(m_client); + m_client->didFinishURLImport(); + m_client = 0; + } +}; + +static void performWorkItem(void* context) +{ + ClientWorkItem* item = static_cast<ClientWorkItem*>(context); + item->performWork(); + delete item; +} + +void IconDatabase::dispatchDidImportIconURLForPageURLOnMainThread(const String& pageURL) +{ + ASSERT_ICON_SYNC_THREAD(); + + ImportedIconURLForPageURLWorkItem* work = new ImportedIconURLForPageURLWorkItem(m_client, pageURL); + callOnMainThread(performWorkItem, work); +} + +void IconDatabase::dispatchDidImportIconDataForPageURLOnMainThread(const String& pageURL) +{ + ASSERT_ICON_SYNC_THREAD(); + + ImportedIconDataForPageURLWorkItem* work = new ImportedIconDataForPageURLWorkItem(m_client, pageURL); + callOnMainThread(performWorkItem, work); +} + +void IconDatabase::dispatchDidRemoveAllIconsOnMainThread() +{ + ASSERT_ICON_SYNC_THREAD(); + + RemovedAllIconsWorkItem* work = new RemovedAllIconsWorkItem(m_client); + callOnMainThread(performWorkItem, work); +} + +void IconDatabase::dispatchDidFinishURLImportOnMainThread() +{ + ASSERT_ICON_SYNC_THREAD(); + + FinishedURLImport* work = new FinishedURLImport(m_client); + callOnMainThread(performWorkItem, work); +} + + } // namespace WebCore #endif // ENABLE(ICONDATABASE) diff --git a/Source/WebCore/loader/icon/IconDatabase.h b/Source/WebCore/loader/icon/IconDatabase.h index 8617430..7392245 100644 --- a/Source/WebCore/loader/icon/IconDatabase.h +++ b/Source/WebCore/loader/icon/IconDatabase.h @@ -27,17 +27,20 @@ #ifndef IconDatabase_h #define IconDatabase_h +#include "IconDatabaseBase.h" #include "Timer.h" #include <wtf/HashMap.h> #include <wtf/HashSet.h> #include <wtf/Noncopyable.h> #include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> #include <wtf/text/StringHash.h> +#include <wtf/text/WTFString.h> #if ENABLE(ICONDATABASE) #include "SQLiteDatabase.h" #include <wtf/Threading.h> -#endif +#endif // ENABLE(ICONDATABASE) namespace WebCore { @@ -56,41 +59,48 @@ class SharedBuffer; class SQLTransaction; #endif -enum IconLoadDecision { - IconLoadYes, - IconLoadNo, - IconLoadUnknown +#if !ENABLE(ICONDATABASE) +// For builds with IconDatabase disabled, they'll just use a default derivation of IconDatabaseBase. Which does nothing. +class IconDatabase : public IconDatabaseBase { +public: + static void delayDatabaseCleanup() { } + static String defaultDatabaseFilename() { return "WebpageIcons.db"; } }; +#else -class IconDatabase { - WTF_MAKE_NONCOPYABLE(IconDatabase); WTF_MAKE_FAST_ALLOCATED; +class IconDatabase : public IconDatabaseBase { + WTF_MAKE_FAST_ALLOCATED; + // *** Main Thread Only *** public: - void setClient(IconDatabaseClient*); + static PassOwnPtr<IconDatabase> create() { return new IconDatabase; } + ~IconDatabase(); + + virtual void setClient(IconDatabaseClient*); - bool open(const String& path); - void close(); + virtual bool open(const String& directory, const String& filename); + virtual void close(); - void removeAllIcons(); + virtual void removeAllIcons(); - Image* iconForPageURL(const String&, const IntSize&); void readIconForPageURLFromDisk(const String&); - String iconURLForPageURL(const String&); - Image* defaultIcon(const IntSize&); - void retainIconForPageURL(const String&); - void releaseIconForPageURL(const String&); + virtual Image* defaultIcon(const IntSize&); - void setIconDataForIconURL(PassRefPtr<SharedBuffer> data, const String&); - void setIconURLForPageURL(const String& iconURL, const String& pageURL); + virtual void retainIconForPageURL(const String&); + virtual void releaseIconForPageURL(const String&); + virtual void setIconDataForIconURL(PassRefPtr<SharedBuffer> data, const String&); + virtual void setIconURLForPageURL(const String& iconURL, const String& pageURL); - IconLoadDecision loadDecisionForIconURL(const String&, DocumentLoader*); - bool iconDataKnownForIconURL(const String&); + virtual Image* synchronousIconForPageURL(const String&, const IntSize&); + virtual String synchronousIconURLForPageURL(const String&); + virtual bool synchronousIconDataKnownForIconURL(const String&); + virtual IconLoadDecision synchronousLoadDecisionForIconURL(const String&, DocumentLoader*); - void setEnabled(bool enabled); - bool isEnabled() const; + virtual void setEnabled(bool); + virtual bool isEnabled() const; - void setPrivateBrowsingEnabled(bool flag); + virtual void setPrivateBrowsingEnabled(bool flag); bool isPrivateBrowsingEnabled() const; static void delayDatabaseCleanup(); @@ -98,17 +108,15 @@ public: static void checkIntegrityBeforeOpening(); // Support for WebCoreStatistics in WebKit - size_t pageURLMappingCount(); - size_t retainedPageURLCount(); - size_t iconRecordCount(); - size_t iconRecordCountWithData(); + virtual size_t pageURLMappingCount(); + virtual size_t retainedPageURLCount(); + virtual size_t iconRecordCount(); + virtual size_t iconRecordCountWithData(); private: IconDatabase(); - ~IconDatabase(); - friend IconDatabase& iconDatabase(); + friend IconDatabaseBase& iconDatabase(); -#if ENABLE(ICONDATABASE) static void notifyPendingLoadDecisionsOnMainThread(void*); void notifyPendingLoadDecisions(); @@ -123,15 +131,13 @@ private: HashSet<RefPtr<DocumentLoader> > m_loadersPendingDecision; RefPtr<IconRecord> m_defaultIconRecord; -#endif // ENABLE(ICONDATABASE) // *** Any Thread *** public: - bool isOpen() const; - String databasePath() const; + virtual bool isOpen() const; + virtual String databasePath() const; static String defaultDatabaseFilename(); -#if ENABLE(ICONDATABASE) private: PassRefPtr<IconRecord> getOrCreateIconRecord(const String& iconURL); PageURLRecord* getOrCreatePageURLRecord(const String& pageURL); @@ -166,17 +172,15 @@ private: HashSet<String> m_pageURLsPendingImport; HashSet<String> m_pageURLsInterestedInIcons; HashSet<IconRecord*> m_iconsPendingReading; -#endif // ENABLE(ICONDATABASE) // *** Sync Thread Only *** public: // Should be used only on the sync thread and only by the Safari 2 Icons import procedure - void importIconURLForPageURL(const String& iconURL, const String& pageURL); - void importIconDataForIconURL(PassRefPtr<SharedBuffer> data, const String& iconURL); + virtual void importIconURLForPageURL(const String& iconURL, const String& pageURL); + virtual void importIconDataForIconURL(PassRefPtr<SharedBuffer> data, const String& iconURL); - bool shouldStopThreadActivity() const; + virtual bool shouldStopThreadActivity() const; -#if ENABLE(ICONDATABASE) private: static void* iconDatabaseSyncThreadStart(void *); void* iconDatabaseSyncThread(); @@ -213,6 +217,12 @@ private: void removeIconFromSQLDatabase(const String& iconURL); void writeIconSnapshotToSQLDatabase(const IconSnapshot&); + // Methods to dispatch client callbacks on the main thread + void dispatchDidImportIconURLForPageURLOnMainThread(const String&); + void dispatchDidImportIconDataForPageURLOnMainThread(const String&); + void dispatchDidRemoveAllIconsOnMainThread(); + void dispatchDidFinishURLImportOnMainThread(); + // The client is set by the main thread before the thread starts, and from then on is only used by the sync thread IconDatabaseClient* m_client; @@ -236,11 +246,9 @@ private: OwnPtr<SQLiteStatement> m_updateIconDataStatement; OwnPtr<SQLiteStatement> m_setIconInfoStatement; OwnPtr<SQLiteStatement> m_setIconDataStatement; -#endif // ENABLE(ICONDATABASE) }; -// Function to obtain the global icon database. -IconDatabase& iconDatabase(); +#endif // !ENABLE(ICONDATABASE) } // namespace WebCore diff --git a/Source/WebCore/loader/icon/IconDatabaseBase.cpp b/Source/WebCore/loader/icon/IconDatabaseBase.cpp new file mode 100644 index 0000000..f552412 --- /dev/null +++ b/Source/WebCore/loader/icon/IconDatabaseBase.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "IconDatabaseBase.h" + +#include "IconDatabase.h" +#include "SharedBuffer.h" + +namespace WebCore { + +String IconDatabaseBase::synchronousIconURLForPageURL(const String&) +{ + return String(); +} + +String IconDatabaseBase::databasePath() const +{ + return String(); +} + +bool IconDatabaseBase::open(const String&, const String&) +{ + return false; +} + +static IconDatabaseBase* globalDatabase = 0; + +// Functions to get/set the global icon database. +IconDatabaseBase& iconDatabase() +{ + if (globalDatabase) + return *globalDatabase; + + static IconDatabaseBase* defaultDatabase = 0; + if (!defaultDatabase) + defaultDatabase = new IconDatabase; + + return *defaultDatabase; +} + +void setGlobalIconDatabase(IconDatabaseBase* newGlobalDatabase) +{ + globalDatabase = newGlobalDatabase; +} + +} // namespace WebCore diff --git a/Source/WebCore/loader/icon/IconDatabaseBase.h b/Source/WebCore/loader/icon/IconDatabaseBase.h new file mode 100644 index 0000000..bc665ba --- /dev/null +++ b/Source/WebCore/loader/icon/IconDatabaseBase.h @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef IconDatabaseBase_h +#define IconDatabaseBase_h + +#include "SharedBuffer.h" + +#include <wtf/Forward.h> +#include <wtf/Noncopyable.h> +#include <wtf/PassRefPtr.h> + +namespace WebCore { + +class DocumentLoader; +class IconDatabaseClient; +class Image; +class IntSize; + +enum IconLoadDecision { + IconLoadYes, + IconLoadNo, + IconLoadUnknown +}; + +class CallbackBase : public RefCounted<CallbackBase> { +public: + virtual ~CallbackBase() + { + } + + uint64_t callbackID() const { return m_callbackID; } + +protected: + CallbackBase(void* context) + : m_context(context) + , m_callbackID(generateCallbackID()) + { + } + + void* context() const { return m_context; } + +private: + static uint64_t generateCallbackID() + { + static uint64_t uniqueCallbackID = 1; + return uniqueCallbackID++; + } + + void* m_context; + uint64_t m_callbackID; +}; + +template<typename EnumType> +class EnumCallback : public CallbackBase { +public: + typedef void (*CallbackFunction)(EnumType, void*); + + static PassRefPtr<EnumCallback> create(void* context, CallbackFunction callback) + { + return adoptRef(new EnumCallback(context, callback)); + } + + virtual ~EnumCallback() + { + ASSERT(!m_callback); + } + + void performCallback(EnumType result) + { + if (!m_callback) + return; + m_callback(result, context()); + m_callback = 0; + } + + void invalidate() + { + m_callback = 0; + } + +private: + EnumCallback(void* context, CallbackFunction callback) + : CallbackBase(context) + , m_callback(callback) + { + ASSERT(m_callback); + } + + CallbackFunction m_callback; +}; + +template<typename ObjectType> +class ObjectCallback : public CallbackBase { +public: + typedef void (*CallbackFunction)(ObjectType, void*); + + static PassRefPtr<ObjectCallback> create(void* context, CallbackFunction callback) + { + return adoptRef(new ObjectCallback(context, callback)); + } + + virtual ~ObjectCallback() + { + ASSERT(!m_callback); + } + + void performCallback(ObjectType result) + { + if (!m_callback) + return; + m_callback(result, context()); + m_callback = 0; + } + + void invalidate() + { + m_callback = 0; + } + +private: + ObjectCallback(void* context, CallbackFunction callback) + : CallbackBase(context) + , m_callback(callback) + { + ASSERT(m_callback); + } + + CallbackFunction m_callback; +}; + +typedef EnumCallback<IconLoadDecision> IconLoadDecisionCallback; +typedef ObjectCallback<SharedBuffer*> IconDataCallback; + +class IconDatabaseBase { + WTF_MAKE_NONCOPYABLE(IconDatabaseBase); + +protected: + IconDatabaseBase() { } + +public: + virtual ~IconDatabaseBase() { } + + // Used internally by WebCore + virtual bool isEnabled() const { return false; } + + virtual void retainIconForPageURL(const String&) { } + virtual void releaseIconForPageURL(const String&) { } + + virtual void setIconURLForPageURL(const String&, const String&) { } + virtual void setIconDataForIconURL(PassRefPtr<SharedBuffer>, const String&) { } + + // Synchronous calls used internally by WebCore. + // Usage should be replaced by asynchronous calls. + virtual String synchronousIconURLForPageURL(const String&); + virtual bool synchronousIconDataKnownForIconURL(const String&) { return false; } + virtual IconLoadDecision synchronousLoadDecisionForIconURL(const String&, DocumentLoader*) { return IconLoadNo; } + virtual Image* synchronousIconForPageURL(const String&, const IntSize&) { return 0; } + + // Asynchronous calls we should use to replace the above when supported. + virtual bool supportsAsynchronousMode() { return false; } + virtual void loadDecisionForIconURL(const String&, PassRefPtr<IconLoadDecisionCallback>) { } + virtual void iconDataForIconURL(const String&, PassRefPtr<IconDataCallback>) { } + + + // Used within one or more WebKit ports. + // We should try to remove these dependencies from the IconDatabaseBase class. + virtual void setEnabled(bool) { } + + virtual Image* defaultIcon(const IntSize&) { return 0; } + + virtual size_t pageURLMappingCount() { return 0; } + virtual size_t retainedPageURLCount() { return 0; } + virtual size_t iconRecordCount() { return 0; } + virtual size_t iconRecordCountWithData() { return 0; } + + virtual void importIconURLForPageURL(const String&, const String&) { } + virtual void importIconDataForIconURL(PassRefPtr<SharedBuffer>, const String&) { } + virtual bool shouldStopThreadActivity() const { return true; } + + virtual bool open(const String& directory, const String& filename); + virtual void close() { } + virtual void removeAllIcons() { } + + virtual void setPrivateBrowsingEnabled(bool) { } + virtual void setClient(IconDatabaseClient*) { } + + virtual bool isOpen() const { return false; } + virtual String databasePath() const; + +}; + +// Functions to get/set the global icon database. +IconDatabaseBase& iconDatabase(); +void setGlobalIconDatabase(IconDatabaseBase*); + +} // namespace WebCore + +#endif // IconDatabaseBase_h diff --git a/Source/WebCore/loader/icon/IconDatabaseClient.h b/Source/WebCore/loader/icon/IconDatabaseClient.h index f97a2a8..3d5f349 100644 --- a/Source/WebCore/loader/icon/IconDatabaseClient.h +++ b/Source/WebCore/loader/icon/IconDatabaseClient.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2011 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,23 +29,20 @@ #ifndef IconDatabaseClient_h #define IconDatabaseClient_h -#include <wtf/FastAllocBase.h> #include <wtf/Forward.h> -#include <wtf/Noncopyable.h> - -// All of these client methods will be called from a non-main thread -// Take appropriate measures namespace WebCore { class IconDatabaseClient { - WTF_MAKE_NONCOPYABLE(IconDatabaseClient); WTF_MAKE_FAST_ALLOCATED; public: - IconDatabaseClient() { } virtual ~IconDatabaseClient() { } - virtual bool performImport() { return true; } - virtual void dispatchDidRemoveAllIcons() { } - virtual void dispatchDidAddIconForPageURL(const String& /*pageURL*/) { } + + virtual bool performImport() = 0; + virtual void didImportIconURLForPageURL(const String&) = 0; + virtual void didImportIconDataForPageURL(const String&) = 0; + virtual void didChangeIconForPageURL(const String&) = 0; + virtual void didRemoveAllIcons() = 0; + virtual void didFinishURLImport() = 0; }; } // namespace WebCore diff --git a/Source/WebCore/loader/icon/IconDatabaseNone.cpp b/Source/WebCore/loader/icon/IconDatabaseNone.cpp deleted file mode 100644 index de28cdd..0000000 --- a/Source/WebCore/loader/icon/IconDatabaseNone.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "IconDatabase.h" - -#if !ENABLE(ICONDATABASE) - -#include "PlatformString.h" -#include "SharedBuffer.h" -#include <wtf/StdLibExtras.h> - -namespace WebCore { - -static IconDatabase* sharedIconDatabase = 0; - -// This version number is in the DB and marks the current generation of the schema -// Theoretically once the switch is flipped this should never change -// Currently, an out-of-date schema causes the DB to be wiped and reset. This isn't -// so bad during development but in the future, we would need to write a conversion -// function to advance older released schemas to "current" -const int currentDatabaseVersion = 5; - -// Icons expire once a day -const int iconExpirationTime = 60*60*24; -// Absent icons are rechecked once a week -const int missingIconExpirationTime = 60*60*24*7; - -const int updateTimerDelay = 5; - -String IconDatabase::defaultDatabaseFilename() -{ - DEFINE_STATIC_LOCAL(String, defaultDatabaseFilename, ("Icons.db")); - return defaultDatabaseFilename.threadsafeCopy(); -} - -IconDatabase& iconDatabase() -{ - if (!sharedIconDatabase) - sharedIconDatabase = new IconDatabase; - return *sharedIconDatabase; -} - -IconDatabase::IconDatabase() -{ -} - -bool IconDatabase::open(const String& /*databasePath*/) -{ - return false; -} - -bool IconDatabase::isOpen() const -{ - return false; -} - -void IconDatabase::close() -{ -} - -String IconDatabase::databasePath() const -{ - return String(); -} - -void IconDatabase::removeAllIcons() -{ -} - -void IconDatabase::setPrivateBrowsingEnabled(bool /*flag*/) -{ -} - -bool IconDatabase::isPrivateBrowsingEnabled() const -{ - return false; -} - -void IconDatabase::readIconForPageURLFromDisk(const String&) -{ - -} - -Image* IconDatabase::iconForPageURL(const String& /*pageURL*/, const IntSize& size) -{ - return defaultIcon(size); -} - - -IconLoadDecision IconDatabase::loadDecisionForIconURL(const String&, DocumentLoader*) -{ - return IconLoadNo; -} - -bool IconDatabase::iconDataKnownForIconURL(const String&) -{ - return false; -} - -String IconDatabase::iconURLForPageURL(const String& /*pageURL*/) -{ - return String(); -} - -Image* IconDatabase::defaultIcon(const IntSize& /*size*/) -{ - return 0; -} - -void IconDatabase::retainIconForPageURL(const String& /*pageURL*/) -{ -} - -void IconDatabase::releaseIconForPageURL(const String& /*pageURL*/) -{ -} - -void IconDatabase::setIconDataForIconURL(PassRefPtr<SharedBuffer> /*data*/, const String& /*iconURL*/) -{ -} - -void IconDatabase::setIconURLForPageURL(const String& /*iconURL*/, const String& /*pageURL*/) -{ -} - -void IconDatabase::setEnabled(bool /*enabled*/) -{ -} - -bool IconDatabase::isEnabled() const -{ - return false; -} - -IconDatabase::~IconDatabase() -{ - ASSERT_NOT_REACHED(); -} - -void IconDatabase::checkIntegrityBeforeOpening() -{ -} - -void IconDatabase::delayDatabaseCleanup() -{ -} - -void IconDatabase::allowDatabaseCleanup() -{ -} - -size_t IconDatabase::pageURLMappingCount() -{ - return 0; -} - -size_t IconDatabase::retainedPageURLCount() -{ - return 0; -} - -size_t IconDatabase::iconRecordCount() -{ - return 0; -} - -size_t IconDatabase::iconRecordCountWithData() -{ - return 0; -} - -void IconDatabase::setClient(IconDatabaseClient*) -{ -} - -// ************************ -// *** Sync Thread Only *** -// ************************ - -void IconDatabase::importIconURLForPageURL(const String&, const String&) -{ -} - -void IconDatabase::importIconDataForIconURL(PassRefPtr<SharedBuffer>, const String&) -{ -} - -bool IconDatabase::shouldStopThreadActivity() const -{ - return true; -} - -} // namespace WebCore - -#endif // !ENABLE(ICONDATABASE) diff --git a/Source/WebCore/loader/mac/ResourceLoaderMac.mm b/Source/WebCore/loader/mac/ResourceLoaderMac.mm index 3835517..b42f8e0 100644 --- a/Source/WebCore/loader/mac/ResourceLoaderMac.mm +++ b/Source/WebCore/loader/mac/ResourceLoaderMac.mm @@ -35,6 +35,10 @@ #include "FrameLoaderClient.h" #include "ResourceHandle.h" +#if HAVE(CFNETWORK_DATA_ARRAY_CALLBACK) +#include "InspectorInstrumentation.h" +#endif + namespace WebCore { NSCachedURLResponse* ResourceLoader::willCacheResponse(ResourceHandle*, NSCachedURLResponse* response) @@ -44,6 +48,44 @@ NSCachedURLResponse* ResourceLoader::willCacheResponse(ResourceHandle*, NSCached return frameLoader()->client()->willCacheResponse(documentLoader(), identifier(), response); } +#if HAVE(CFNETWORK_DATA_ARRAY_CALLBACK) + +void ResourceLoader::didReceiveDataArray(CFArrayRef dataArray) +{ + // Protect this in this delegate method since the additional processing can do + // anything including possibly derefing this; one example of this is Radar 3266216. + RefPtr<ResourceLoader> protector(this); + + if (!m_shouldBufferData) + return; + + if (!m_resourceData) + m_resourceData = SharedBuffer::create(); + + CFIndex arrayCount = CFArrayGetCount(dataArray); + for (CFIndex i = 0; i < arrayCount; ++i) { + CFDataRef data = static_cast<CFDataRef>(CFArrayGetValueAtIndex(dataArray, i)); + int dataLen = static_cast<int>(CFDataGetLength(data)); + + m_resourceData->append(data); + + // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing. + // However, with today's computers and networking speeds, this won't happen in practice. + // Could be an issue with a giant local file. + if (m_sendResourceLoadCallbacks && m_frame) + frameLoader()->notifier()->didReceiveData(this, reinterpret_cast<const char*>(CFDataGetBytePtr(data)), dataLen, dataLen); + } +} + +void ResourceLoader::didReceiveDataArray(ResourceHandle*, CFArrayRef dataArray) +{ + InspectorInstrumentationCookie cookie = InspectorInstrumentation::willReceiveResourceData(m_frame.get(), identifier()); + didReceiveDataArray(dataArray); + InspectorInstrumentation::didReceiveResourceData(cookie); +} + +#endif + } #endif // !USE(CFNETWORK) |