blob: de1250ecde976a62f2258c7dc74f6e8ec374b2c8 [file] [log] [blame]
/*
* Copyright (C) 2014 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "WebKitDLL.h"
#include "WebApplicationCache.h"
#include "CFDictionaryPropertyBag.h"
#include "MarshallingHelpers.h"
#include "WebPreferences.h"
#include "WebSecurityOrigin.h"
#include <WebCore/ApplicationCache.h>
#include <WebCore/ApplicationCacheStorage.h>
#include <WebCore/COMPtr.h>
#include <WebCore/SecurityOrigin.h>
#include <comutil.h>
#include <wtf/FileSystem.h>
#include <wtf/RetainPtr.h>
using namespace WebCore;
#if USE(CF)
static CFStringRef WebKitLocalCacheDefaultsKey = CFSTR("WebKitLocalCache");
#endif
// WebApplicationCache ---------------------------------------------------------------------------
WebApplicationCache::WebApplicationCache()
: m_refCount(0)
{
gClassCount++;
gClassNameCount().add("WebApplicationCache");
}
WebApplicationCache::~WebApplicationCache()
{
gClassCount--;
gClassNameCount().remove("WebApplicationCache");
}
WebApplicationCache* WebApplicationCache::createInstance()
{
WebApplicationCache* instance = new WebApplicationCache();
instance->AddRef();
return instance;
}
static String applicationCachePath()
{
String path = FileSystem::localUserSpecificStorageDirectory();
#if USE(CF)
auto cacheDirectoryPreference = adoptCF(CFPreferencesCopyAppValue(WebKitLocalCacheDefaultsKey, WebPreferences::applicationId()));
if (cacheDirectoryPreference && CFStringGetTypeID() == CFGetTypeID(cacheDirectoryPreference.get()))
path = static_cast<CFStringRef>(cacheDirectoryPreference.get());
#endif
return path;
}
WebCore::ApplicationCacheStorage& WebApplicationCache::storage()
{
static ApplicationCacheStorage& storage = ApplicationCacheStorage::create(applicationCachePath(), "ApplicationCache").leakRef();
return storage;
}
// IUnknown -------------------------------------------------------------------
HRESULT WebApplicationCache::QueryInterface(_In_ REFIID riid, _COM_Outptr_ void** ppvObject)
{
if (!ppvObject)
return E_POINTER;
*ppvObject = nullptr;
if (IsEqualGUID(riid, IID_IUnknown))
*ppvObject = static_cast<WebApplicationCache*>(this);
else if (IsEqualGUID(riid, IID_IWebApplicationCache))
*ppvObject = static_cast<WebApplicationCache*>(this);
else
return E_NOINTERFACE;
AddRef();
return S_OK;
}
ULONG WebApplicationCache::AddRef()
{
return ++m_refCount;
}
ULONG WebApplicationCache::Release()
{
ULONG newRef = --m_refCount;
if (!newRef)
delete(this);
return newRef;
}
// IWebApplicationCache ------------------------------------------------------------------------------
HRESULT WebApplicationCache::maximumSize(long long* size)
{
if (!size)
return E_POINTER;
*size = storage().maximumSize();
return S_OK;
}
HRESULT WebApplicationCache::setMaximumSize(long long size)
{
storage().deleteAllEntries();
storage().setMaximumSize(size);
return S_OK;
}
HRESULT WebApplicationCache::defaultOriginQuota(long long* quota)
{
if (!quota)
return E_POINTER;
*quota = storage().defaultOriginQuota();
return S_OK;
}
HRESULT WebApplicationCache::setDefaultOriginQuota(long long quota)
{
storage().setDefaultOriginQuota(quota);
return S_OK;
}
HRESULT WebApplicationCache::diskUsageForOrigin(IWebSecurityOrigin* origin, long long* size)
{
if (!origin || !size)
return E_POINTER;
COMPtr<WebSecurityOrigin> webSecurityOrigin(Query, origin);
if (!webSecurityOrigin)
return E_FAIL;
*size = storage().diskUsageForOrigin(*webSecurityOrigin->securityOrigin());
return S_OK;
}
HRESULT WebApplicationCache::deleteAllApplicationCaches()
{
storage().deleteAllCaches();
return S_OK;
}
HRESULT WebApplicationCache::deleteCacheForOrigin(IWebSecurityOrigin* origin)
{
if (!origin)
return E_POINTER;
COMPtr<WebSecurityOrigin> webSecurityOrigin(Query, origin);
if (!webSecurityOrigin)
return E_FAIL;
storage().deleteCacheForOrigin(*webSecurityOrigin->securityOrigin());
return S_OK;
}
HRESULT WebApplicationCache::originsWithCache(IPropertyBag** origins)
{
if (!origins)
return E_POINTER;
auto coreOrigins = storage().originsWithCache();
#if USE(CF)
RetainPtr<CFMutableArrayRef> arrayItem = adoptCF(CFArrayCreateMutable(kCFAllocatorDefault, coreOrigins.size(), &MarshallingHelpers::kIUnknownArrayCallBacks));
for (auto& coreOrigin : coreOrigins)
CFArrayAppendValue(arrayItem.get(), reinterpret_cast<void*>(WebSecurityOrigin::createInstance(coreOrigin.ptr())));
RetainPtr<CFMutableDictionaryRef> dictionary = adoptCF(
CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
RetainPtr<CFStringRef> key = adoptCF(MarshallingHelpers::BSTRToCFStringRef(_bstr_t(L"origins")));
CFDictionaryAddValue(dictionary.get(), key.get(), arrayItem.get());
COMPtr<CFDictionaryPropertyBag> result = CFDictionaryPropertyBag::createInstance();
result->setDictionary(dictionary.get());
*origins = result.leakRef();
#endif
return S_OK;
}