1/*
2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "WebDatabaseManager.h"
28
29#include "Connection.h"
30#include "MessageID.h"
31#include "OriginAndDatabases.h"
32#include "WebCoreArgumentCoders.h"
33#include "WebDatabaseManagerProxyMessages.h"
34#include "WebProcess.h"
35#include <WebCore/DatabaseDetails.h>
36#include <WebCore/DatabaseTracker.h>
37#include <WebCore/SecurityOrigin.h>
38
39using namespace WebCore;
40
41namespace WebKit {
42
43WebDatabaseManager& WebDatabaseManager::shared()
44{
45    static WebDatabaseManager& shared = *new WebDatabaseManager;
46    return shared;
47}
48
49void WebDatabaseManager::initialize(const String& databaseDirectory)
50{
51    DatabaseTracker::initializeTracker(databaseDirectory);
52}
53
54WebDatabaseManager::WebDatabaseManager()
55{
56    DatabaseTracker::tracker().setClient(this);
57}
58
59WebDatabaseManager::~WebDatabaseManager()
60{
61}
62
63void WebDatabaseManager::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
64{
65    didReceiveWebDatabaseManagerMessage(connection, messageID, arguments);
66}
67
68void WebDatabaseManager::getDatabasesByOrigin(uint64_t callbackID) const
69{
70    WebProcess::LocalTerminationDisabler terminationDisabler(WebProcess::shared());
71
72    // FIXME: This could be made more efficient by adding a function to DatabaseTracker
73    // to get both the origins and the Vector of DatabaseDetails for each origin in one
74    // shot.  That would avoid taking the numerous locks this requires.
75
76    Vector<RefPtr<SecurityOrigin> > origins;
77    DatabaseTracker::tracker().origins(origins);
78
79    Vector<OriginAndDatabases> originAndDatabasesVector;
80    originAndDatabasesVector.reserveInitialCapacity(origins.size());
81
82    for (size_t i = 0; i < origins.size(); ++i) {
83        OriginAndDatabases originAndDatabases;
84
85        Vector<String> nameVector;
86        if (!DatabaseTracker::tracker().databaseNamesForOrigin(origins[i].get(), nameVector))
87            continue;
88
89        Vector<DatabaseDetails> detailsVector;
90        detailsVector.reserveInitialCapacity(nameVector.size());
91        for (size_t j = 0; j < nameVector.size(); j++) {
92            DatabaseDetails details = DatabaseTracker::tracker().detailsForNameAndOrigin(nameVector[j], origins[i].get());
93            if (details.name().isNull())
94                continue;
95
96            detailsVector.append(details);
97        }
98
99        if (detailsVector.isEmpty())
100            continue;
101
102        originAndDatabases.originIdentifier = origins[i]->databaseIdentifier();
103        originAndDatabases.originQuota = DatabaseTracker::tracker().quotaForOrigin(origins[i].get());
104        originAndDatabases.originUsage = DatabaseTracker::tracker().usageForOrigin(origins[i].get());
105        originAndDatabases.databases.swap(detailsVector);
106        originAndDatabasesVector.append(originAndDatabases);
107    }
108
109    WebProcess::shared().connection()->send(Messages::WebDatabaseManagerProxy::DidGetDatabasesByOrigin(originAndDatabasesVector, callbackID), 0);
110}
111
112void WebDatabaseManager::getDatabaseOrigins(uint64_t callbackID) const
113{
114    WebProcess::LocalTerminationDisabler terminationDisabler(WebProcess::shared());
115
116    Vector<RefPtr<SecurityOrigin> > origins;
117    DatabaseTracker::tracker().origins(origins);
118
119    size_t numOrigins = origins.size();
120
121    Vector<String> identifiers(numOrigins);
122    for (size_t i = 0; i < numOrigins; ++i)
123        identifiers[i] = origins[i]->databaseIdentifier();
124    WebProcess::shared().connection()->send(Messages::WebDatabaseManagerProxy::DidGetDatabaseOrigins(identifiers, callbackID), 0);
125}
126
127void WebDatabaseManager::deleteDatabaseWithNameForOrigin(const String& databaseIdentifier, const String& originIdentifier) const
128{
129    WebProcess::LocalTerminationDisabler terminationDisabler(WebProcess::shared());
130
131    RefPtr<SecurityOrigin> origin = SecurityOrigin::createFromDatabaseIdentifier(originIdentifier);
132    if (!origin)
133        return;
134
135    DatabaseTracker::tracker().deleteDatabase(origin.get(), databaseIdentifier);
136}
137
138void WebDatabaseManager::deleteDatabasesForOrigin(const String& originIdentifier) const
139{
140    WebProcess::LocalTerminationDisabler terminationDisabler(WebProcess::shared());
141
142    RefPtr<SecurityOrigin> origin = SecurityOrigin::createFromDatabaseIdentifier(originIdentifier);
143    if (!origin)
144        return;
145
146    DatabaseTracker::tracker().deleteOrigin(origin.get());
147}
148
149void WebDatabaseManager::deleteAllDatabases() const
150{
151    WebProcess::LocalTerminationDisabler terminationDisabler(WebProcess::shared());
152
153    DatabaseTracker::tracker().deleteAllDatabases();
154}
155
156void WebDatabaseManager::setQuotaForOrigin(const String& originIdentifier, unsigned long long quota) const
157{
158    WebProcess::LocalTerminationDisabler terminationDisabler(WebProcess::shared());
159
160    // If the quota is set to a value lower than the current usage, that quota will
161    // "stick" but no data will be purged to meet the new quota. This will simply
162    // prevent new data from being added to databases in that origin.
163
164    RefPtr<SecurityOrigin> origin = SecurityOrigin::createFromDatabaseIdentifier(originIdentifier);
165    if (!origin)
166        return;
167
168    DatabaseTracker::tracker().setQuota(origin.get(), quota);
169}
170
171void WebDatabaseManager::dispatchDidModifyOrigin(SecurityOrigin* origin)
172{
173    // NOTE: This may be called on a non-main thread.
174    WebProcess::shared().connection()->send(Messages::WebDatabaseManagerProxy::DidModifyOrigin(origin->databaseIdentifier()), 0);
175}
176
177void WebDatabaseManager::dispatchDidModifyDatabase(WebCore::SecurityOrigin* origin, const String& databaseIdentifier)
178{
179    // NOTE: This may be called on a non-main thread.
180    WebProcess::shared().connection()->send(Messages::WebDatabaseManagerProxy::DidModifyDatabase(origin->databaseIdentifier(), databaseIdentifier), 0);
181}
182
183} // namespace WebKit
184