IDBFactoryBackendProxy.cpp [plain text]
#include "config.h"
#include "IDBFactoryBackendProxy.h"
#if ENABLE(INDEXED_DATABASE)
#include "CrossThreadTask.h"
#include "DOMStringList.h"
#include "IDBDatabaseBackendProxy.h"
#include "IDBDatabaseError.h"
#include "SecurityOrigin.h"
#include "WebFrameImpl.h"
#include "WebIDBCallbacksImpl.h"
#include "WebIDBDatabase.h"
#include "WebIDBDatabaseError.h"
#include "WebIDBFactory.h"
#include "WebKit.h"
#include "platform/WebKitPlatformSupport.h"
#include "WebPermissionClient.h"
#include "platform/WebVector.h"
#include "WebViewImpl.h"
#include "WebWorkerBase.h"
#include "WebWorkerClientImpl.h"
#include "WorkerContext.h"
#include "WorkerLoaderProxy.h"
#include "WorkerScriptController.h"
#include "WorkerThread.h"
using namespace WebCore;
namespace WebKit {
PassRefPtr<IDBFactoryBackendInterface> IDBFactoryBackendProxy::create()
{
return adoptRef(new IDBFactoryBackendProxy());
}
IDBFactoryBackendProxy::IDBFactoryBackendProxy()
: m_webIDBFactory(webKitPlatformSupport()->idbFactory())
{
}
IDBFactoryBackendProxy::~IDBFactoryBackendProxy()
{
}
void IDBFactoryBackendProxy::getDatabaseNames(PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<SecurityOrigin> prpOrigin, Frame* frame, const String& dataDir)
{
WebSecurityOrigin origin(prpOrigin);
WebFrameImpl* webFrame = WebFrameImpl::fromFrame(frame);
WebViewImpl* webView = webFrame->viewImpl();
if (webView->permissionClient() && !webView->permissionClient()->allowIndexedDB(webFrame, "Database Listing", origin)) {
callbacks->onError(WebIDBDatabaseError(0, "The user denied permission to access the database."));
return;
}
m_webIDBFactory->getDatabaseNames(new WebIDBCallbacksImpl(callbacks), origin, webFrame, dataDir);
}
static const char allowIndexedDBMode[] = "allowIndexedDBMode";
class AllowIndexedDBMainThreadBridge : public ThreadSafeRefCounted<AllowIndexedDBMainThreadBridge> {
public:
static PassRefPtr<AllowIndexedDBMainThreadBridge> create(WebWorkerBase* webWorkerBase, const String& mode, const String& name)
{
return adoptRef(new AllowIndexedDBMainThreadBridge(webWorkerBase, mode, name));
}
void cancel()
{
MutexLocker locker(m_mutex);
m_webWorkerBase = 0;
}
bool result()
{
return m_result;
}
void signalCompleted(bool result, const String& mode)
{
MutexLocker locker(m_mutex);
if (m_webWorkerBase)
m_webWorkerBase->postTaskForModeToWorkerContext(createCallbackTask(&didComplete, this, result), mode);
}
private:
AllowIndexedDBMainThreadBridge(WebWorkerBase* webWorkerBase, const String& mode, const String& name)
: m_result(false)
, m_webWorkerBase(webWorkerBase)
{
WebCommonWorkerClient* commonClient = webWorkerBase->commonClient();
WebWorkerBase::dispatchTaskToMainThread(
createCallbackTask(&allowIndexedDBTask, this, WebCore::AllowCrossThreadAccess(commonClient), name, mode));
}
static void allowIndexedDBTask(ScriptExecutionContext*, PassRefPtr<AllowIndexedDBMainThreadBridge> bridge, WebCommonWorkerClient* commonClient, const String& name, const String& mode)
{
if (!commonClient) {
bridge->signalCompleted(false, mode);
return;
}
bool allowed = commonClient->allowIndexedDB(name);
bridge->signalCompleted(allowed, mode);
}
static void didComplete(ScriptExecutionContext* context, PassRefPtr<AllowIndexedDBMainThreadBridge> bridge, bool result)
{
bridge->m_result = result;
}
bool m_result;
Mutex m_mutex;
WebWorkerBase* m_webWorkerBase;
};
bool IDBFactoryBackendProxy::allowIDBFromWorkerThread(WorkerContext* workerContext, const String& name, const WebSecurityOrigin&)
{
WebWorkerBase* webWorkerBase = static_cast<WebWorkerBase*>(&workerContext->thread()->workerLoaderProxy());
WorkerRunLoop& runLoop = workerContext->thread()->runLoop();
String mode = allowIndexedDBMode;
mode.append(String::number(runLoop.createUniqueId()));
RefPtr<AllowIndexedDBMainThreadBridge> bridge = AllowIndexedDBMainThreadBridge::create(webWorkerBase, mode, name);
if (runLoop.runInMode(workerContext, mode) == MessageQueueTerminated) {
bridge->cancel();
return false;
}
return bridge->result();
}
void IDBFactoryBackendProxy::openFromWorker(const String& name, IDBCallbacks* callbacks, PassRefPtr<SecurityOrigin> prpOrigin, WorkerContext* context, const String& dataDir)
{
#if ENABLE(WORKERS)
WebSecurityOrigin origin(prpOrigin);
if (!allowIDBFromWorkerThread(context, name, origin)) {
callbacks->onError(WebIDBDatabaseError(0, "The user denied permission to access the database."));
return;
}
m_webIDBFactory->open(name, new WebIDBCallbacksImpl(callbacks), origin, 0, dataDir);
#endif
}
void IDBFactoryBackendProxy::open(const String& name, IDBCallbacks* callbacks, PassRefPtr<SecurityOrigin> prpOrigin, Frame* frame, const String& dataDir)
{
WebSecurityOrigin origin(prpOrigin);
WebFrameImpl* webFrame = WebFrameImpl::fromFrame(frame);
WebViewImpl* webView = webFrame->viewImpl();
if (webView->permissionClient() && !webView->permissionClient()->allowIndexedDB(webFrame, name, origin)) {
callbacks->onError(WebIDBDatabaseError(0, "The user denied permission to access the database."));
return;
}
m_webIDBFactory->open(name, new WebIDBCallbacksImpl(callbacks), origin, webFrame, dataDir);
}
void IDBFactoryBackendProxy::deleteDatabase(const String& name, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<SecurityOrigin> prpOrigin, Frame* frame, const String& dataDir)
{
WebSecurityOrigin origin(prpOrigin);
WebFrameImpl* webFrame = WebFrameImpl::fromFrame(frame);
WebViewImpl* webView = webFrame->viewImpl();
if (webView->permissionClient() && !webView->permissionClient()->allowIndexedDB(webFrame, name, origin)) {
callbacks->onError(WebIDBDatabaseError(0, "The user denied permission to access the database."));
return;
}
m_webIDBFactory->deleteDatabase(name, new WebIDBCallbacksImpl(callbacks), origin, webFrame, dataDir);
}
}
#endif // ENABLE(INDEXED_DATABASE)