Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / modules / webdatabase / DatabaseContext.cpp
1 /*
2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3  * Copyright (C) 2011 Google, Inc. All Rights Reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27
28 #include "config.h"
29 #include "modules/webdatabase/DatabaseContext.h"
30
31 #include "core/dom/Document.h"
32 #include "core/dom/ExecutionContext.h"
33 #include "modules/webdatabase/Database.h"
34 #include "modules/webdatabase/DatabaseManager.h"
35 #include "modules/webdatabase/DatabaseTask.h"
36 #include "modules/webdatabase/DatabaseThread.h"
37 #include "platform/weborigin/SchemeRegistry.h"
38 #include "platform/weborigin/SecurityOrigin.h"
39 #include "wtf/Assertions.h"
40
41 namespace WebCore {
42
43 // How the DatabaseContext Life-Cycle works?
44 // ========================================
45 // ... in other words, who's keeping the DatabaseContext alive and how long does
46 // it need to stay alive?
47 //
48 // The DatabaseContext is referenced from RefPtrs in:
49 // 1. ExecutionContext
50 // 2. Database
51 //
52 // At Birth:
53 // ========
54 // We create a DatabaseContext only when there is a need i.e. the script tries to
55 // open a Database via DatabaseManager::openDatabase().
56 //
57 // The DatabaseContext constructor will call ref(). This lets DatabaseContext keep itself alive.
58 // Note that paired deref() is called from contextDestroyed().
59 //
60 // Once a DatabaseContext is associated with a ExecutionContext, it will
61 // live until after the ExecutionContext destructs. This is true even if
62 // we don't succeed in opening any Databases for that context. When we do
63 // succeed in opening Databases for this ExecutionContext, the Database
64 // will re-use the same DatabaseContext.
65 //
66 // At Shutdown:
67 // ===========
68 // During shutdown, the DatabaseContext needs to:
69 // 1. "outlive" the ExecutionContext.
70 //    - This is needed because the DatabaseContext needs to remove itself from the
71 //      ExecutionContext's ActiveDOMObject list and ContextLifecycleObserver
72 //      list. This removal needs to be executed on the script's thread. Hence, we
73 //      rely on the ExecutionContext's shutdown process to call
74 //      stop() and contextDestroyed() to give us a chance to clean these up from
75 //      the script thread.
76 //
77 // 2. "outlive" the Databases.
78 //    - This is because they may make use of the DatabaseContext to execute a close
79 //      task and shutdown in an orderly manner. When the Databases are destructed,
80 //      they will deref the DatabaseContext from the DatabaseThread.
81 //
82 // During shutdown, the ExecutionContext is shutting down on the script thread
83 // while the Databases are shutting down on the DatabaseThread. Hence, there can be
84 // a race condition as to whether the ExecutionContext or the Databases
85 // destruct first.
86 //
87 // The RefPtrs in the Databases and ExecutionContext will ensure that the
88 // DatabaseContext will outlive both regardless of which of the 2 destructs first.
89
90 PassRefPtrWillBeRawPtr<DatabaseContext> DatabaseContext::create(ExecutionContext* context)
91 {
92     RefPtrWillBeRawPtr<DatabaseContext> self = adoptRefWillBeNoop(new DatabaseContext(context));
93     DatabaseManager::manager().registerDatabaseContext(self.get());
94     return self.release();
95 }
96
97 DatabaseContext::DatabaseContext(ExecutionContext* context)
98     : ActiveDOMObject(context)
99     , m_hasOpenDatabases(false)
100     , m_hasRequestedTermination(false)
101 {
102     // ActiveDOMObject expects this to be called to set internal flags.
103     suspendIfNeeded();
104
105     // For debug accounting only. We must do this before we register the
106     // instance. The assertions assume this.
107     DatabaseManager::manager().didConstructDatabaseContext();
108     if (context->isWorkerGlobalScope())
109         toWorkerGlobalScope(context)->registerTerminationObserver(this);
110 }
111
112 DatabaseContext::~DatabaseContext()
113 {
114     // For debug accounting only. We must call this last. The assertions assume
115     // this.
116     DatabaseManager::manager().didDestructDatabaseContext();
117 }
118
119 void DatabaseContext::trace(Visitor* visitor)
120 {
121     visitor->trace(m_databaseThread);
122     visitor->trace(m_openSyncDatabases);
123 }
124
125 // This is called if the associated ExecutionContext is destructing while
126 // we're still associated with it. That's our cue to disassociate and shutdown.
127 // To do this, we stop the database and let everything shutdown naturally
128 // because the database closing process may still make use of this context.
129 // It is not safe to just delete the context here.
130 void DatabaseContext::contextDestroyed()
131 {
132     RefPtrWillBeRawPtr<DatabaseContext> protector(this);
133     stopDatabases();
134     if (executionContext()->isWorkerGlobalScope())
135         toWorkerGlobalScope(executionContext())->unregisterTerminationObserver(this);
136     DatabaseManager::manager().unregisterDatabaseContext(this);
137     ActiveDOMObject::contextDestroyed();
138 }
139
140 void DatabaseContext::wasRequestedToTerminate()
141 {
142     DatabaseManager::manager().interruptAllDatabasesForContext(this);
143 }
144
145 // stop() is from stopActiveDOMObjects() which indicates that the owner LocalFrame
146 // or WorkerThread is shutting down. Initiate the orderly shutdown by stopping
147 // the associated databases.
148 void DatabaseContext::stop()
149 {
150     stopDatabases();
151 }
152
153 DatabaseContext* DatabaseContext::backend()
154 {
155     return this;
156 }
157
158 DatabaseThread* DatabaseContext::databaseThread()
159 {
160     if (!m_databaseThread && !m_hasOpenDatabases) {
161         // It's OK to ask for the m_databaseThread after we've requested
162         // termination because we're still using it to execute the closing
163         // of the database. However, it is NOT OK to create a new thread
164         // after we've requested termination.
165         ASSERT(!m_hasRequestedTermination);
166
167         // Create the database thread on first request - but not if at least one database was already opened,
168         // because in that case we already had a database thread and terminated it and should not create another.
169         m_databaseThread = DatabaseThread::create();
170         m_databaseThread->start();
171     }
172
173     return m_databaseThread.get();
174 }
175
176 void DatabaseContext::didOpenDatabase(DatabaseBackendBase& database)
177 {
178     if (!database.isSyncDatabase())
179         return;
180     ASSERT(isContextThread());
181 #if ENABLE(OILPAN)
182     m_openSyncDatabases.add(&database, adoptPtr(new DatabaseCloser(database)));
183 #else
184     m_openSyncDatabases.add(&database);
185 #endif
186 }
187
188 void DatabaseContext::didCloseDatabase(DatabaseBackendBase& database)
189 {
190 #if !ENABLE(OILPAN)
191     if (!database.isSyncDatabase())
192         return;
193     ASSERT(isContextThread());
194     m_openSyncDatabases.remove(&database);
195 #endif
196 }
197
198 #if ENABLE(OILPAN)
199 DatabaseContext::DatabaseCloser::~DatabaseCloser()
200 {
201     m_database.closeImmediately();
202 }
203 #endif
204
205 void DatabaseContext::stopSyncDatabases()
206 {
207     // SQLite is "multi-thread safe", but each database handle can only be used
208     // on a single thread at a time.
209     //
210     // For DatabaseBackendSync, we open the SQLite database on the script
211     // context thread. And hence we should also close it on that same
212     // thread. This means that the SQLite database need to be closed here in the
213     // destructor.
214     ASSERT(isContextThread());
215 #if ENABLE(OILPAN)
216     m_openSyncDatabases.clear();
217 #else
218     Vector<DatabaseBackendBase*> syncDatabases;
219     copyToVector(m_openSyncDatabases, syncDatabases);
220     m_openSyncDatabases.clear();
221     for (size_t i = 0; i < syncDatabases.size(); ++i)
222         syncDatabases[i]->closeImmediately();
223 #endif
224 }
225
226 void DatabaseContext::stopDatabases()
227 {
228     stopSyncDatabases();
229
230     // Though we initiate termination of the DatabaseThread here in
231     // stopDatabases(), we can't clear the m_databaseThread ref till we get to
232     // the destructor. This is because the Databases that are managed by
233     // DatabaseThread still rely on this ref between the context and the thread
234     // to execute the task for closing the database. By the time we get to the
235     // destructor, we're guaranteed that the databases are destructed (which is
236     // why our ref count is 0 then and we're destructing). Then, the
237     // m_databaseThread RefPtr destructor will deref and delete the
238     // DatabaseThread.
239
240     if (m_databaseThread && !m_hasRequestedTermination) {
241         TaskSynchronizer sync;
242         m_databaseThread->requestTermination(&sync);
243         m_hasRequestedTermination = true;
244         sync.waitForTaskCompletion();
245     }
246 }
247
248 bool DatabaseContext::allowDatabaseAccess() const
249 {
250     if (executionContext()->isDocument())
251         return toDocument(executionContext())->isActive();
252     ASSERT(executionContext()->isWorkerGlobalScope());
253     // allowDatabaseAccess is not yet implemented for workers.
254     return true;
255 }
256
257 SecurityOrigin* DatabaseContext::securityOrigin() const
258 {
259     return executionContext()->securityOrigin();
260 }
261
262 bool DatabaseContext::isContextThread() const
263 {
264     return executionContext()->isContextThread();
265 }
266
267 } // namespace WebCore