Apply quota policy for indexed database
authorJiyeon Kim <jiyeon0402.kim@samsung.com>
Fri, 22 Mar 2013 06:17:48 +0000 (15:17 +0900)
committerGerrit Code Review <gerrit2@kim11>
Mon, 1 Apr 2013 08:44:11 +0000 (17:44 +0900)
[Title] Apply quota policy for indexed database
[Problem] N/A
[Cause] N/A
[Solution] Check quota limitation before making objectStore, index and put data for objectStore
- Default quota : 100*1024*1024
- Maximum quota : 2*1024*1024*1024
- ewk_view_exceeded_indexed_database_quota_callback_set() is added for calling the callback when request quota for UA
- ewk_view_exceeded_indexed_database_quota_reply() is added to allow/deny quota

Change-Id: I24e47c9b2955fb2ee63a9265c46a5f376391db56

29 files changed:
Source/WebCore/Modules/indexeddb/IDBBackingStore.h
Source/WebCore/Modules/indexeddb/IDBDatabase.cpp
Source/WebCore/Modules/indexeddb/IDBDatabase.h
Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.cpp
Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.h
Source/WebCore/Modules/indexeddb/IDBDatabaseBackendInterface.h
Source/WebCore/Modules/indexeddb/IDBLevelDBBackingStore.cpp
Source/WebCore/Modules/indexeddb/IDBLevelDBBackingStore.h
Source/WebCore/Modules/indexeddb/IDBObjectStore.cpp
Source/WebCore/Modules/indexeddb/IDBObjectStore.h
Source/WebCore/Modules/indexeddb/IDBObjectStoreBackendImpl.cpp
Source/WebCore/Modules/indexeddb/IDBObjectStoreBackendImpl.h
Source/WebCore/Modules/indexeddb/IDBObjectStoreBackendInterface.h
Source/WebCore/loader/EmptyClients.h
Source/WebCore/page/ChromeClient.h
Source/WebKit2/UIProcess/API/C/efl/tizen/WKPageTizen.cpp
Source/WebKit2/UIProcess/API/C/efl/tizen/WKPageTizen.h
Source/WebKit2/UIProcess/API/efl/ewk_view.cpp
Source/WebKit2/UIProcess/API/efl/ewk_view.h
Source/WebKit2/UIProcess/API/efl/ewk_view_private.h
Source/WebKit2/UIProcess/API/efl/ewk_view_tizen_client.cpp
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/UIProcess/WebPageProxy.messages.in
Source/WebKit2/UIProcess/efl/WebPageProxyEfl.cpp
Source/WebKit2/UIProcess/tizen/WebTizenClient.cpp
Source/WebKit2/UIProcess/tizen/WebTizenClient.h
Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.cpp
Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.h
Source/WebKit2/WebProcess/WebPage/WebPage.cpp

index 90c85c1..0626d09 100644 (file)
@@ -118,6 +118,10 @@ public:
         virtual void rollback() = 0;
     };
     virtual PassRefPtr<Transaction> createTransaction() = 0;
+
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    virtual String databaseDirectory() = 0;
+#endif
 };
 
 } // namespace WebCore
index a32eab1..8e8fba2 100644 (file)
 #include "ScriptExecutionContext.h"
 #include <limits>
 
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+#include "Chrome.h"
+#include "ChromeClient.h"
+#include "Document.h"
+#include "Page.h"
+#include "PageGroup.h"
+#endif
+
 namespace WebCore {
 
 PassRefPtr<IDBDatabase> IDBDatabase::create(ScriptExecutionContext* context, PassRefPtr<IDBDatabaseBackendInterface> database, PassRefPtr<IDBDatabaseCallbacks> callbacks)
@@ -156,6 +164,12 @@ PassRefPtr<IDBObjectStore> IDBDatabase::createObjectStore(const String& name, co
         return 0;
     }
 
+
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    if (exceededDatabase(ec))
+        return 0;
+#endif
+
     RefPtr<IDBObjectStoreBackendInterface> objectStoreBackend = m_backend->createObjectStore(name, keyPath, autoIncrement, m_versionChangeTransaction->backend(), ec);
     if (!objectStoreBackend) {
         ASSERT(ec);
@@ -371,6 +385,31 @@ EventTargetData* IDBDatabase::ensureEventTargetData()
     return &m_eventTargetData;
 }
 
+bool IDBDatabase::exceededDatabase(ExceptionCode& ec)
+{
+    Document* document = static_cast<Document*>(scriptExecutionContext());
+    int64_t defaultQuota = document->page()->group().groupSettings()->indexedDBQuotaBytes();
+    int64_t maxQuota = 0x80000000; // 2GB
+
+    int64_t totalSize = m_backend->getDatabaseFileSize(ec);
+    if (ec)
+        return true;
+
+    if (totalSize > maxQuota) {
+        ec = IDBDatabaseException::IDB_QUOTA_EXCEEDED_ERR;
+        return true;
+    }
+
+    if (totalSize >= defaultQuota && defaultQuota != maxQuota) {
+        if(document->page()->chrome()->client()->exceededIndexedDatabaseQuota(document->frame(), totalSize))
+            document->page()->group().groupSettings()->setIndexedDBQuotaBytes(maxQuota);
+        else {
+            ec = IDBDatabaseException::IDB_QUOTA_EXCEEDED_ERR;
+            return true;
+        }
+    }
+    return false;
+}
 } // namespace WebCore
 
 #endif // ENABLE(INDEXED_DATABASE)
index cdc7c2b..433c382 100644 (file)
@@ -110,6 +110,10 @@ private:
 
     void closeConnection();
 
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    bool exceededDatabase(ExceptionCode&);
+#endif
+
     IDBDatabaseMetadata m_metadata;
     RefPtr<IDBDatabaseBackendInterface> m_backend;
     RefPtr<IDBTransaction> m_versionChangeTransaction;
index 9d17c56..0d18008 100755 (executable)
 #include "IDBTransactionBackendImpl.h"
 #include "IDBTransactionCoordinator.h"
 
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+#include "FileSystem.h"
+#endif
+
 namespace WebCore {
 
 class IDBDatabaseBackendImpl::PendingOpenCall : public RefCounted<PendingOpenCall> {
@@ -630,6 +634,30 @@ void IDBDatabaseBackendImpl::resetVersion(ScriptExecutionContext*, PassRefPtr<ID
     database->m_version = previousVersion;
     database->m_intVersion = previousIntVersion;
 }
+
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+String IDBDatabaseBackendImpl::databaseDirectory()
+{
+     return m_backingStore->databaseDirectory();
+}
+
+int64_t IDBDatabaseBackendImpl::getDatabaseFileSize(ExceptionCode& ec)
+{
+    String fullPath = IDBDatabaseBackendImpl::databaseDirectory();
+    int64_t totalSize = 0;
+    Vector<String> paths = WebCore::listDirectory(fullPath, ("*"));
+    size_t pathsCount = paths.size();
+    for (size_t i = 0; i< pathsCount; ++i) {
+        int64_t size = 0;
+        if (!getFileSize(paths[i], size)) {
+            ec = IDBDatabaseException::DATA_ERR;
+            return false;
+        }
+        totalSize += size;
+    }
+    return totalSize;
+}
+#endif
 } // namespace WebCore
 
 #endif // ENABLE(INDEXED_DATABASE)
index 69cd60d..c6920fc 100755 (executable)
@@ -73,6 +73,9 @@ public:
     void transactionFinished(PassRefPtr<IDBTransactionBackendImpl>);
     void transactionFinishedAndCompleteFired(PassRefPtr<IDBTransactionBackendImpl>);
     void transactionFinishedAndAbortFired(PassRefPtr<IDBTransactionBackendImpl>);
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    int64_t getDatabaseFileSize(ExceptionCode& ec);
+#endif
 
 private:
     IDBDatabaseBackendImpl(const String& name, IDBBackingStore* database, IDBTransactionCoordinator*, IDBFactoryBackendImpl*, const String& uniqueIdentifier);
@@ -92,6 +95,10 @@ private:
     static void removeObjectStoreFromMap(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl>, PassRefPtr<IDBObjectStoreBackendImpl>);
     static void addObjectStoreToMap(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl>, PassRefPtr<IDBObjectStoreBackendImpl>);
     static void resetVersion(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl>, const String& version, int64_t intVersion);
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    String databaseDirectory();
+#endif
+
 
     RefPtr<IDBBackingStore> m_backingStore;
     int64_t m_id;
index fa789c5..b9f9958 100644 (file)
@@ -59,6 +59,10 @@ public:
     virtual void setVersion(const String& version, PassRefPtr<IDBCallbacks>, PassRefPtr<IDBDatabaseCallbacks>, ExceptionCode&) = 0;
     virtual PassRefPtr<IDBTransactionBackendInterface> transaction(DOMStringList* storeNames, unsigned short mode, ExceptionCode&) = 0;
     virtual void close(PassRefPtr<IDBDatabaseCallbacks>) = 0;
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    virtual int64_t getDatabaseFileSize(ExceptionCode& ec) = 0;
+#endif
+
 };
 
 } // namespace WebCore
index 06d5777..22e17ac 100644 (file)
@@ -207,6 +207,10 @@ PassRefPtr<IDBBackingStore> IDBLevelDBBackingStore::open(SecurityOrigin* securit
     OwnPtr<LevelDBComparator> comparator = adoptPtr(new Comparator());
     OwnPtr<LevelDBDatabase> db;
 
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    String path = pathByAppendingComponent(pathBase, securityOrigin->databaseIdentifier() + ".indexeddb.leveldb");
+#endif
+
     if (pathBase.isEmpty())
         db = LevelDBDatabase::openInMemory(comparator.get());
     else {
@@ -215,8 +219,9 @@ PassRefPtr<IDBBackingStore> IDBLevelDBBackingStore::open(SecurityOrigin* securit
             return PassRefPtr<IDBBackingStore>();
         }
         // FIXME: We should eventually use the same LevelDB database for all origins.
+#if !ENABLE(TIZEN_INDEXED_DATABASE)
         String path = pathByAppendingComponent(pathBase, securityOrigin->databaseIdentifier() + ".indexeddb.leveldb");
-
+#endif
         db = LevelDBDatabase::open(path, comparator.get());
 
         if (!db) {
@@ -243,7 +248,9 @@ PassRefPtr<IDBBackingStore> IDBLevelDBBackingStore::open(SecurityOrigin* securit
 
     RefPtr<IDBLevelDBBackingStore> backingStore(adoptRef(new IDBLevelDBBackingStore(fileIdentifier, factory, db.release())));
     backingStore->m_comparator = comparator.release();
-
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    backingStore->m_databaseDirectory = path;
+#endif
     if (!setUpMetadata(backingStore->m_db.get(), fileIdentifier))
         return PassRefPtr<IDBBackingStore>();
 
index c3759cf..bf9a44b 100644 (file)
@@ -81,6 +81,10 @@ public:
 
     static bool backingStoreExists(SecurityOrigin*, const String& name, const String& pathBase);
 
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    virtual String databaseDirectory() { return m_databaseDirectory; }
+#endif
+
 protected:
     IDBLevelDBBackingStore(const String& identifier, IDBFactoryBackendImpl*, PassOwnPtr<LevelDBDatabase>);
 
@@ -92,6 +96,9 @@ private:
     OwnPtr<LevelDBDatabase> m_db;
     OwnPtr<LevelDBComparator> m_comparator;
     RefPtr<LevelDBTransaction> m_currentTransaction;
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    String m_databaseDirectory;
+#endif
 
     class Transaction : public IDBBackingStore::Transaction {
     public:
index 381076d..1e1234c 100644 (file)
 #include "SerializedScriptValue.h"
 #include <wtf/UnusedParam.h>
 
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+#include "Chrome.h"
+#include "ChromeClient.h"
+#include "Document.h"
+#include "FileSystem.h"
+#include "Page.h"
+#include "PageGroup.h"
+#endif
+
 namespace WebCore {
 
 static const unsigned short defaultDirection = IDBCursor::NEXT;
@@ -174,6 +183,11 @@ PassRefPtr<IDBRequest> IDBObjectStore::put(IDBObjectStoreBackendInterface::PutMo
     ScriptExecutionContext* context = scriptExecutionContextFromScriptState(state);
     DOMRequestState requestState(context);
 
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    if (exceededDatabase(context, ec))
+        return 0;
+#endif
+
     if (putMode != IDBObjectStoreBackendInterface::CursorUpdate && usesInLineKeys && key) {
         ec = IDBDatabaseException::DATA_ERR;
         return 0;
@@ -418,6 +432,11 @@ PassRefPtr<IDBIndex> IDBObjectStore::createIndex(ScriptExecutionContext* context
         return 0;
     }
 
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    if (exceededDatabase(context, ec))
+        return 0;
+#endif
+
     RefPtr<IDBIndexBackendInterface> indexBackend = m_backend->createIndex(name, keyPath, unique, multiEntry, m_transaction->backend(), ec);
     ASSERT(!indexBackend != !ec); // If we didn't get an index, we should have gotten an exception code. And vice versa.
     if (ec)
@@ -593,6 +612,34 @@ void IDBObjectStore::transactionFinished()
 }
 
 
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+bool IDBObjectStore::exceededDatabase(ScriptExecutionContext* context, ExceptionCode& ec)
+{
+    Document* document = static_cast<Document*>(context);
+    int64_t defaultQuota = document->page()->group().groupSettings()->indexedDBQuotaBytes();
+    int64_t maxQuota = 0x80000000; // 2GB
+
+    int64_t totalSize = m_backend->getDatabaseFileSize(ec);
+    if (ec)
+        return true;
+
+    if (totalSize > maxQuota) {
+        ec = IDBDatabaseException::IDB_QUOTA_EXCEEDED_ERR;
+        return true;
+    }
+
+    if (totalSize >= defaultQuota && defaultQuota != maxQuota) {
+        if (document->page()->chrome()->client()->exceededIndexedDatabaseQuota(document->frame(), totalSize))
+            document->page()->group().groupSettings()->setIndexedDBQuotaBytes(maxQuota);
+        else {
+            ec = IDBDatabaseException::IDB_QUOTA_EXCEEDED_ERR;
+            return true;
+        }
+    }
+    return false;
+}
+#endif
+
 } // namespace WebCore
 
 #endif // ENABLE(INDEXED_DATABASE)
index 72b89fb..d1b0ac0 100644 (file)
@@ -109,6 +109,9 @@ public:
 
 private:
     IDBObjectStore(const IDBObjectStoreMetadata&, PassRefPtr<IDBObjectStoreBackendInterface>, IDBTransaction*);
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    bool exceededDatabase(ScriptExecutionContext*, ExceptionCode&);
+#endif
 
     IDBObjectStoreMetadata m_metadata;
     RefPtr<IDBObjectStoreBackendInterface> m_backend;
index 0e0bf48..c7c84d2 100755 (executable)
 #include "IDBTransactionBackendImpl.h"
 #include "ScriptExecutionContext.h"
 
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+#include "FileSystem.h"
+#endif
+
 namespace WebCore {
 
 IDBObjectStoreBackendImpl::~IDBObjectStoreBackendImpl()
@@ -601,7 +605,25 @@ void IDBObjectStoreBackendImpl::updateKeyGenerator(const IDBKey* key, bool check
     backingStore()->maybeUpdateKeyGeneratorCurrentNumber(databaseId(), id(), static_cast<int64_t>(floor(key->number())) + 1, checkCurrent);
 }
 
-
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+int64_t IDBObjectStoreBackendImpl::getDatabaseFileSize(ExceptionCode& ec)
+{
+    String fullPath = backingStore()->databaseDirectory();
+    int64_t totalSize = 0;
+
+    Vector<String> paths = WebCore::listDirectory(fullPath, ("*"));
+    size_t pathsCount = paths.size();
+    for (size_t i = 0; i< pathsCount; ++i) {
+        int64_t size = 0;
+        if (!getFileSize(paths[i], size)) {
+            ec = IDBDatabaseException::DATA_ERR;
+            return false;
+        }
+        totalSize += size;
+    }
+    return totalSize;
+}
+#endif
 } // namespace WebCore
 
 #endif
index a1080f1..32c0bdc 100644 (file)
@@ -95,6 +95,10 @@ public:
     PassRefPtr<IDBBackingStore> backingStore() const { return m_database->backingStore(); }
     int64_t databaseId() const { return m_database->id(); }
 
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    int64_t getDatabaseFileSize(ExceptionCode& ec);
+#endif
+
 private:
     IDBObjectStoreBackendImpl(const IDBDatabaseBackendImpl*, int64_t databaseId, const String& name, const IDBKeyPath&, bool autoIncrement);
     IDBObjectStoreBackendImpl(const IDBDatabaseBackendImpl*, const String& name, const IDBKeyPath&, bool autoIncrement);
index 86667ab..182e278 100644 (file)
@@ -71,6 +71,10 @@ public:
 
     virtual void openCursor(PassRefPtr<IDBKeyRange>, IDBCursor::Direction, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface::TaskType, IDBTransactionBackendInterface*, ExceptionCode&) = 0;
     virtual void count(PassRefPtr<IDBKeyRange>, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&) = 0;
+
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    virtual int64_t getDatabaseFileSize(ExceptionCode& ec) = 0;
+#endif
 };
 
 } // namespace WebCore
index 91b760c..90cb2b3 100755 (executable)
@@ -232,6 +232,11 @@ public:
     virtual void requestVisibleContentRectRestore(const IntPoint& scrollOffset, float scale) { }
     virtual float contentsScaleFactor() const { return 1.0; }
 #endif
+
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    virtual bool exceededIndexedDatabaseQuota(Frame*, int64_t) { }
+#endif
+
 };
 
 class EmptyFrameLoaderClient : public FrameLoaderClient {
index f5b90c8..2f9f7eb 100755 (executable)
@@ -402,6 +402,10 @@ namespace WebCore {
         virtual void rendererWillBeDestroyed(RenderObject*) { }
 #endif
 
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+        virtual bool exceededIndexedDatabaseQuota(Frame*, int64_t) = 0;
+#endif
+
     protected:
         virtual ~ChromeClient() { }
     };
index d3bd7d7..27a1df3 100644 (file)
@@ -127,3 +127,10 @@ void WKPageReplyApplicationCachePermission(WKPageRef page, bool allow)
     toImpl(page)->replyApplicationCachePermission(allow);
 #endif
 }
+
+void WKPageReplyExceededIndexedDatabaseQuota(WKPageRef page, bool allow)
+{
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    toImpl(page)->replyExceededIndexedDatabaseQuota(allow);
+#endif
+}
index 96ee413..09e73e7 100644 (file)
@@ -47,6 +47,9 @@ typedef void (*WKPageJSBridgePluginCallback)(WKPageRef page, WKStringRef request
 // #if ENABLE(TIZEN_CERTIFICATE_HANDLING)
 typedef bool (*WKPageDecidePolicyForCertificateErrorCallback)(WKPageRef page, WKStringRef url, WKStringRef certificate, int error, const void *clientInfo);
 // #endif
+//#if ENABLE(TIZEN_INDEXED_DATABASE)
+typedef bool (*WKPageExceededIndexedDatabaseQuotaCallback)(WKPageRef page, WKSecurityOriginRef origin, long long currentUsage, WKFrameRef frame, const void* clientInfo);
+//#endif
 
 struct WKPageTizenClient {
     int                                                                 version;
@@ -67,6 +70,9 @@ struct WKPageTizenClient {
     // #if ENABLE(TIZEN_CERTIFICATE_HANDLING)
     WKPageDecidePolicyForCertificateErrorCallback               decidePolicyForCertificateError;
     // #endif
+    //#if ENABLE(TIZEN_INDEXED_DATABASE)
+    WKPageExceededIndexedDatabaseQuotaCallback                                  exceededIndexedDatabaseQuota;
+    //#endif
 };
 typedef struct WKPageTizenClient WKPageTizenClient;
 
@@ -109,6 +115,11 @@ WK_EXPORT void WKPageExecuteCommandWithArgument(WKPageRef page, WKStringRef comm
 // #if ENABLE(TIZEN_APPLICATION_CACHE)
 WK_EXPORT void WKPageReplyApplicationCachePermission(WKPageRef page, bool allow);
 // #endif
+
+//#if ENABLE(TIZEN_INDEXED_DATABASE)
+WK_EXPORT void WKPageReplyExceededIndexedDatabaseQuota(WKPageRef page, bool allow);
+//#endif
+
 #ifdef __cplusplus
 }
 #endif
index 6c30cbe..94e0f7c 100755 (executable)
@@ -342,6 +342,11 @@ struct _Ewk_View_Private_Data {
     Ewk_Security_Origin* applicationCachePermissionOrigin;
     bool isWaitingForApplicationCachePermission;
 #endif
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    OwnPtr<Ewk_View_Callback_Context> exceededIndexedDatabaseQuotaContext;
+#endif
+    Ewk_Security_Origin* exceededQuotaOrigin;
+    bool isWaitingForExceededQuotaPopupReply;
 #endif // #if OS(TIZEN)
 
     _Ewk_View_Private_Data()
@@ -412,6 +417,9 @@ struct _Ewk_View_Callback_Context {
 #if ENABLE(TIZEN_APPLICATION_CACHE)
         Ewk_View_Applicacion_Cache_Permission_Callback applicationCachePermissionCallback;
 #endif
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+        Ewk_View_Exceeded_Indexed_Database_Quota_Callback exceededIndexedDatabaseQuotaCallback;
+#endif
     };
 
     Evas_Object* ewkView;
@@ -1290,6 +1298,14 @@ static void _ewk_view_priv_del(Ewk_View_Private_Data* priv)
     priv->isWaitingForApplicationCachePermission = false;
     priv->applicationCachePermissionContext = nullptr;
 #endif
+
+    if (priv->exceededQuotaOrigin)
+        deleteSecurityOrigin(priv->exceededQuotaOrigin);
+    priv->isWaitingForExceededQuotaPopupReply = false;
+
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    priv->exceededIndexedDatabaseQuotaContext = nullptr;
+#endif // #if ENABLE(TIZEN_INDEXED_DATABASE)
 #endif // #if OS(TIZEN)
 
     delete priv;
@@ -3652,7 +3668,7 @@ void ewk_view_suspend(Evas_Object* ewkView)
     // will be suspended again.
     // Multiple suspend of ActiveDOMObject makes unintended suspend/resume status of
     // the ActiveDOMObject.
-    if (!priv->suspendedResources && (!priv->isWaitingForJavaScriptPopupReply || !priv->isWaitingForApplicationCachePermission)) {
+    if (!priv->suspendedResources && (!priv->isWaitingForJavaScriptPopupReply || !priv->isWaitingForApplicationCachePermission || !priv->isWaitingForExceededQuotaPopupReply)) {
         priv->pageClient->page()->suspendJavaScriptAndResource();
         priv->suspendedResources = true;
     }
@@ -3684,7 +3700,7 @@ void ewk_view_resume(Evas_Object* ewkView)
     // will be suspended again.
     // Multiple suspend of ActiveDOMObject makes unintended suspend/resume status of
     // the ActiveDOMObject.
-    if (priv->suspendedResources && (!priv->isWaitingForJavaScriptPopupReply || !priv->isWaitingForApplicationCachePermission)) {
+    if (priv->suspendedResources && (!priv->isWaitingForJavaScriptPopupReply || !priv->isWaitingForApplicationCachePermission || !priv->isWaitingForExceededQuotaPopupReply)) {
         priv->pageClient->page()->resumeJavaScriptAndResource();
         priv->suspendedResources = false;
     }
@@ -5907,3 +5923,58 @@ void ewk_view_application_cache_permission_reply(Evas_Object* ewkView, Eina_Bool
     UNUSED_PARAM(allow);
 #endif
 }
+
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+bool ewkViewExceededIndexedDatabaseQuota(Evas_Object* ewkView, WKSecurityOriginRef origin, long long currentUsage)
+{
+    EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false);
+    EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false);
+
+    if (!priv->exceededIndexedDatabaseQuotaContext || !priv->exceededIndexedDatabaseQuotaContext->exceededIndexedDatabaseQuotaCallback)
+        return false;
+
+    priv->isWaitingForExceededQuotaPopupReply = true;
+    if (priv->exceededQuotaOrigin)
+        deleteSecurityOrigin(priv->exceededQuotaOrigin);
+    priv->exceededQuotaOrigin = createSecurityOrigin(origin);
+
+    TIZEN_LOGI("currentUsage(%lld)", currentUsage);
+
+    return priv->exceededIndexedDatabaseQuotaContext->exceededIndexedDatabaseQuotaCallback(ewkView, priv->exceededQuotaOrigin , currentUsage, priv->exceededIndexedDatabaseQuotaContext->userData) == EINA_TRUE;
+}
+#endif
+
+void ewk_view_exceeded_indexed_database_quota_callback_set(Evas_Object* ewkView, Ewk_View_Exceeded_Indexed_Database_Quota_Callback callback, void* userData)
+{
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData);
+    EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv);
+
+    if (!priv->exceededIndexedDatabaseQuotaContext)
+        priv->exceededIndexedDatabaseQuotaContext = adoptPtr<Ewk_View_Callback_Context>(new Ewk_View_Callback_Context);
+    priv->exceededIndexedDatabaseQuotaContext->exceededIndexedDatabaseQuotaCallback = callback;
+    priv->exceededIndexedDatabaseQuotaContext->userData = userData;
+#else
+    UNUSED_PARAM(ewkView);
+    UNUSED_PARAM(callback);
+    UNUSED_PARAM(userData);
+#endif
+}
+
+void ewk_view_exceeded_indexed_database_quota_reply(Evas_Object* ewkView, Eina_Bool allow)
+{
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData);
+    EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv);
+
+    TIZEN_LOGI("allow %d", allow);
+    WKPageReplyExceededIndexedDatabaseQuota(toAPI(ewk_view_page_get(ewkView)), allow == EINA_TRUE);
+    if (priv->exceededQuotaOrigin)
+        deleteSecurityOrigin(priv->exceededQuotaOrigin);
+    priv->exceededQuotaOrigin = 0;
+    priv->isWaitingForExceededQuotaPopupReply = false;
+#else
+    UNUSED_PARAM(ewkView);
+    UNUSED_PARAM(allow);
+#endif
+}
index d92a24b..9137429 100644 (file)
@@ -696,6 +696,12 @@ EAPI void ewk_view_application_cache_permission_callback_set(Evas_Object* o, Ewk
 EAPI void ewk_view_application_cache_permission_reply(Evas_Object* o, Eina_Bool allow);
 //#endif
 
+//#if ENABLE(TIZEN_INDEXED_DATABASE)
+typedef Eina_Bool (*Ewk_View_Exceeded_Indexed_Database_Quota_Callback)(Evas_Object* o, Ewk_Security_Origin* origin,  long long currentQuota, void* user_data);
+EAPI void ewk_view_exceeded_indexed_database_quota_callback_set(Evas_Object* o, Ewk_View_Exceeded_Indexed_Database_Quota_Callback callback, void* user_data);
+EAPI void ewk_view_exceeded_indexed_database_quota_reply(Evas_Object* o, Eina_Bool allow);
+//#endif
+
 /**
  * Delivers a Web intent to the view's main frame.
  *
index 493c9fc..9fa3c82 100755 (executable)
@@ -376,4 +376,8 @@ void ewkViewBackForwardListChanged(Evas_Object *ewkView);
 #if ENABLE(TIZEN_APPLICATION_CACHE)
 Eina_Bool ewkViewRequestApplicationCachePermission(Evas_Object* ewkView, WKSecurityOriginRef origin);
 #endif
+
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+bool ewkViewExceededIndexedDatabaseQuota(Evas_Object* ewkView, WKSecurityOriginRef origin, long long currentUsage);
+#endif
 #endif // ewk_view_private_h
index 9f47738..707224b 100755 (executable)
@@ -77,6 +77,15 @@ static bool decidePolicyForCertificateError(WKPageRef page, WKStringRef url, WKS
 #endif
 }
 
+static bool exceededIndexedDatabaseQuota(WKPageRef page, WKSecurityOriginRef origin, long long currentUsage, WKFrameRef frame, const void *clientInfo)
+{
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    return ewkViewExceededIndexedDatabaseQuota(static_cast<Evas_Object*>(const_cast<void*>(clientInfo)), origin, currentUsage);
+#else
+    return false;
+#endif
+}
+
 void ewkViewTizenClientAttachClient(Evas_Object* ewkView)
 {
     EINA_SAFETY_ON_NULL_RETURN(ewkView);
@@ -88,7 +97,8 @@ void ewkViewTizenClientAttachClient(Evas_Object* ewkView)
         decidePolicyForApplicationCachePermissionRequest,
         decidePolicyForUserMediaPermissionRequest,
         processJSBridgePlugin,
-        decidePolicyForCertificateError
+        decidePolicyForCertificateError,
+        exceededIndexedDatabaseQuota
     };
 
     WKPageSetPageTizenClient(toAPI(ewk_view_page_get(ewkView)), &tizenClient);
index cac6d50..f8506c7 100755 (executable)
@@ -1023,6 +1023,10 @@ void recordingSurfaceSetEnableSet(bool enable);
     void replyApplicationCachePermission(bool allow);
 #endif
 
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    void replyExceededIndexedDatabaseQuota(bool allow);
+#endif
+
 private:
     WebPageProxy(PageClient*, PassRefPtr<WebProcessProxy>, WebPageGroup*, uint64_t pageID);
 
@@ -1379,6 +1383,10 @@ private:
     void didGetLinkMagnifierRect(const WebCore::IntPoint&, const WebCore::IntRect&);
 #endif
 
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    void exceededIndexedDatabaseQuota(uint64_t frameID, const String& originIdentifier, int64_t currentUsage, PassRefPtr<Messages::WebPageProxy::ExceededIndexedDatabaseQuota::DelayedReply> reply);
+#endif
+
     PageClient* m_pageClient;
     WebLoaderClient m_loaderClient;
     WebPolicyClient m_policyClient;
@@ -1630,6 +1638,10 @@ private:
 #if ENABLE(TIZEN_ISF_PORT)
     bool m_didCancelCompositionFromWebProcess;
 #endif
+
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    RefPtr<Messages::WebPageProxy::ExceededIndexedDatabaseQuota::DelayedReply> m_exceededIndexedDatabaseQuotaReply;
+#endif
 };
 
 } // namespace WebKit
index f57ff42..3ef163e 100755 (executable)
@@ -452,4 +452,8 @@ messages -> WebPageProxy {
     DidScreenReaderFocusRectChanged(WebCore::IntRect rect)
     DidScreenReaderTextChanged(WTF::String text)
 #endif
+
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    ExceededIndexedDatabaseQuota(uint64_t frameID, WTF::String originIdentifier, int64_t currentUsage) -> (bool returnValue) Delayed
+#endif
 }
index 924d426..3afcb7b 100755 (executable)
@@ -1082,7 +1082,39 @@ void WebPageProxy::replyApplicationCachePermission(bool allow)
 
     m_applicationCacheReply->send(allow);
     m_applicationCacheReply = nullptr;
+#if ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
+    process()->connection()->setForcelySetAllAsyncMessagesToDispatchEvenWhenWaitingForSyncReply(false);
+#endif
+}
+#endif
+
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+void WebPageProxy::exceededIndexedDatabaseQuota(uint64_t frameID, const String& originIdentifier, int64_t currentUsage, PassRefPtr<Messages::WebPageProxy::ExceededIndexedDatabaseQuota::DelayedReply> reply)
+{
+    WebFrameProxy* frame = process()->webFrame(frameID);
+    MESSAGE_CHECK(frame);
+
+    // Since exceededIndexedDatabaseQuota() can spin a nested run loop we need to turn off the responsiveness timer.
+    process()->responsivenessTimer()->stop();
+
+    m_exceededIndexedDatabaseQuotaReply = reply;
+#if ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
+    process()->connection()->setForcelySetAllAsyncMessagesToDispatchEvenWhenWaitingForSyncReply(true);
+#endif
+
+    RefPtr<WebSecurityOrigin> origin = WebSecurityOrigin::createFromDatabaseIdentifier(originIdentifier);
+
+    if (!m_tizenClient.exceededIndexedDatabaseQuota(this, origin.get(), currentUsage, frame))
+        replyExceededIndexedDatabaseQuota(false);
+}
+
+void WebPageProxy::replyExceededIndexedDatabaseQuota(bool allow)
+{
+    if (!m_exceededIndexedDatabaseQuotaReply)
+        return;
 
+    m_exceededIndexedDatabaseQuotaReply->send(allow);
+    m_exceededIndexedDatabaseQuotaReply = nullptr;
 #if ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
     process()->connection()->setForcelySetAllAsyncMessagesToDispatchEvenWhenWaitingForSyncReply(false);
 #endif
index 966c5d0..3a1fd5b 100644 (file)
@@ -76,4 +76,14 @@ bool WebTizenClient::decidePolicyForApplicationCachePermissionRequest(WebPagePro
     return m_client.decidePolicyForApplicationCachePermissionRequest(toAPI(page), toAPI(origin), toAPI(frame), m_client.clientInfo);
 }
 #endif
+
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+bool WebTizenClient::exceededIndexedDatabaseQuota(WebPageProxy* page, WebSecurityOrigin* origin, long long currentUsage, WebFrameProxy* frame)
+{
+    if (!m_client.exceededIndexedDatabaseQuota)
+        return currentUsage;
+
+    return m_client.exceededIndexedDatabaseQuota(toAPI(page), toAPI(origin), currentUsage, toAPI(frame), m_client.clientInfo);
+}
+#endif
 } // namespace WebKit
index bf4b864..c653f00 100644 (file)
@@ -63,6 +63,10 @@ public:
 #if ENABLE(TIZEN_APPLICATION_CACHE)
     bool decidePolicyForApplicationCachePermissionRequest(WebPageProxy*, WebSecurityOrigin*, WebFrameProxy*);
 #endif
+
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    bool exceededIndexedDatabaseQuota(WebPageProxy*, WebSecurityOrigin*, long long, WebFrameProxy*);
+#endif
 };
 
 } // namespace WebKit
index 1266154..f447031 100755 (executable)
@@ -990,4 +990,22 @@ void WebChromeClient::rendererWillBeDestroyed(RenderObject* object)
 }
 #endif
 
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+bool WebChromeClient::exceededIndexedDatabaseQuota(Frame* frame, int64_t currentQuota)
+{
+    WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(frame->loader()->client())->webFrame();
+    SecurityOrigin* origin = frame->document()->securityOrigin();
+
+    unsigned syncSendFlags = (WebCore::AXObjectCache::accessibilityEnabled()) ? CoreIPC::SpinRunLoopWhileWaitingForReply : 0;
+    bool allow = false;
+#if ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
+    WebProcess::WaitForJavaScriptPopupFinished waiting;
+#endif
+    if (!WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::ExceededIndexedDatabaseQuota(webFrame->frameID(), origin->databaseIdentifier(), currentQuota), Messages::WebPageProxy::ExceededIndexedDatabaseQuota::Reply(allow), m_page->pageID(), CoreIPC::Connection::DefaultTimeout, syncSendFlags))
+        return false;
+
+    return allow;
+}
+#endif
+
 } // namespace WebKit
index a1aa085..77e53d0 100755 (executable)
@@ -264,6 +264,10 @@ private:
     virtual void rendererWillBeDestroyed(WebCore::RenderObject*);
 #endif
 
+#if ENABLE(TIZEN_INDEXED_DATABASE)
+    virtual bool exceededIndexedDatabaseQuota(Frame*, int64_t) OVERRIDE;
+#endif
+
     String m_cachedToolTip;
     mutable RefPtr<WebFrame> m_cachedFrameSetLargestFrame;
     mutable bool m_cachedMainFrameHasHorizontalScrollbar;
index 1a4e445..de4fc69 100755 (executable)
@@ -2451,6 +2451,7 @@ void WebPage::updatePreferences(const WebPreferencesStore& store)
 
 #if ENABLE(TIZEN_INDEXED_DATABASE)
     m_page->group().groupSettings()->setIndexedDBDatabasePath(WebProcess::shared().indexedDatabaseDirectory());
+    m_page->group().groupSettings()->setIndexedDBQuotaBytes(0x6400000); //100M
 #endif
 
     settings->setDiagnosticLoggingEnabled(store.getBoolValueForKey(WebPreferencesKey::diagnosticLoggingEnabledKey()));