1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file.
4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_factory.h"
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/logging.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/time/time.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_backing_store.h"
111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_context_impl.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_tracing.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_transaction_coordinator.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "webkit/common/database/database_identifier.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace content {
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const int64 kBackingStoreGracePeriodMs = 2000;
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)IndexedDBFactory::IndexedDBFactory(IndexedDBContextImpl* context)
221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    : context_(context) {}
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBFactory::~IndexedDBFactory() {}
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void IndexedDBFactory::ReleaseDatabase(
2758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const IndexedDBDatabase::Identifier& identifier,
281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const GURL& origin_url,
2958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    bool forcedClose) {
301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  IndexedDBDatabaseMap::iterator it = database_map_.find(identifier);
311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(it != database_map_.end());
321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(!it->second->backing_store());
331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  database_map_.erase(it);
3458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
3558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // No grace period on a forced-close, as the initiator is
3658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // assuming the backing store will be released once all
3758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // connections are closed.
381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  ReleaseBackingStore(origin_url, forcedClose);
3958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
4058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void IndexedDBFactory::ReleaseBackingStore(const GURL& origin_url,
4258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                           bool immediate) {
4358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Only close if this is the last reference.
441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!HasLastBackingStoreReference(origin_url))
4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return;
4658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // If this factory does hold the last reference to the backing store, it can
481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // be closed - but unless requested to close it immediately, keep it around
491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // for a short period so that a re-open is fast.
5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (immediate) {
511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    CloseBackingStore(origin_url);
5258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return;
5358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
5458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Start a timer to close the backing store, unless something else opens it
561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // in the mean time.
571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(!backing_store_map_[origin_url]->close_timer()->IsRunning());
581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  backing_store_map_[origin_url]->close_timer()->Start(
5958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      FROM_HERE,
6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      base::TimeDelta::FromMilliseconds(kBackingStoreGracePeriodMs),
611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      base::Bind(&IndexedDBFactory::MaybeCloseBackingStore, this, origin_url));
6258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
6358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void IndexedDBFactory::MaybeCloseBackingStore(const GURL& origin_url) {
651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Another reference may have opened since the maybe-close was posted, so it
661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // is necessary to check again.
671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (HasLastBackingStoreReference(origin_url))
681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    CloseBackingStore(origin_url);
6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void IndexedDBFactory::CloseBackingStore(const GURL& origin_url) {
721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  IndexedDBBackingStoreMap::iterator it = backing_store_map_.find(origin_url);
731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(it != backing_store_map_.end());
741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Stop the timer (if it's running) - this may happen if the timer was started
751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // and then a forced close occurs.
761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  it->second->close_timer()->Stop();
771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  backing_store_map_.erase(it);
7858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool IndexedDBFactory::HasLastBackingStoreReference(const GURL& origin_url)
811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const {
8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  IndexedDBBackingStore* ptr;
8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  {
8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Scope so that the implicit scoped_refptr<> is freed.
8558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    IndexedDBBackingStoreMap::const_iterator it =
861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        backing_store_map_.find(origin_url);
8758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DCHECK(it != backing_store_map_.end());
8858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ptr = it->second.get();
8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return ptr->HasOneRef();
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void IndexedDBFactory::ForceClose(const GURL& origin_url) {
94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (backing_store_map_.find(origin_url) != backing_store_map_.end())
95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ReleaseBackingStore(origin_url, true /* immediate */);
96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void IndexedDBFactory::ContextDestroyed() {
991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Timers on backing stores hold a reference to this factory. When the
1001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // context (which nominally owns this factory) is destroyed during thread
1011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // termination the timers must be stopped so that this factory and the
1021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // stores can be disposed of.
1031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (IndexedDBBackingStoreMap::iterator it = backing_store_map_.begin();
1041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)       it != backing_store_map_.end();
1051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)       ++it)
1061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    it->second->close_timer()->Stop();
1071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  backing_store_map_.clear();
1081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  context_ = NULL;
1091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBFactory::GetDatabaseNames(
112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks,
1131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const GURL& origin_url,
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const base::FilePath& data_directory) {
115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBFactory::GetDatabaseNames");
116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(dgrogan): Plumb data_loss back to script eventually?
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  blink::WebIDBDataLoss data_loss;
1180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  std::string data_loss_message;
11968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bool disk_full;
1201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_refptr<IndexedDBBackingStore> backing_store =
1210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      OpenBackingStore(origin_url,
1220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                       data_directory,
1230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                       &data_loss,
1240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                       &data_loss_message,
1250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                       &disk_full);
126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!backing_store) {
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnError(
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "Internal error opening backing store for "
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               "indexedDB.webkitGetDatabaseNames."));
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  callbacks->OnSuccess(backing_store->GetDatabaseNames());
135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ReleaseBackingStore(origin_url, false /* immediate */);
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBFactory::DeleteDatabase(
139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& name,
140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks,
1411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const GURL& origin_url,
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const base::FilePath& data_directory) {
143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBFactory::DeleteDatabase");
1441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  IndexedDBDatabase::Identifier unique_identifier(origin_url, name);
145424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier);
146424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (it != database_map_.end()) {
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // If there are any connections to the database, directly delete the
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // database.
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    it->second->DeleteDatabase(callbacks);
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(dgrogan): Plumb data_loss back to script eventually?
154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  blink::WebIDBDataLoss data_loss;
1550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  std::string data_loss_message;
15668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bool disk_full = false;
1571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_refptr<IndexedDBBackingStore> backing_store =
1580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      OpenBackingStore(origin_url,
1590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                       data_directory,
1600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                       &data_loss,
1610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                       &data_loss_message,
1620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                       &disk_full);
163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!backing_store) {
164424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    callbacks->OnError(
165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
166424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                               ASCIIToUTF16(
167424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   "Internal error opening backing store "
168424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   "for indexedDB.deleteDatabase.")));
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
172424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_refptr<IndexedDBDatabase> database =
173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      IndexedDBDatabase::Create(name, backing_store, this, unique_identifier);
174424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!database) {
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callbacks->OnError(IndexedDBDatabaseError(
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        blink::WebIDBDatabaseExceptionUnknownError,
177424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        ASCIIToUTF16(
178424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            "Internal error creating database backend for "
179424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            "indexedDB.deleteDatabase.")));
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
183424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  database_map_[unique_identifier] = database;
184424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  database->DeleteDatabase(callbacks);
185424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  database_map_.erase(unique_identifier);
186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ReleaseBackingStore(origin_url, false /* immediate */);
187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void IndexedDBFactory::HandleBackingStoreFailure(const GURL& origin_url) {
1901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // NULL after ContextDestroyed() called, and in some unit tests.
1911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!context_)
1921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return;
1931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  context_->ForceClose(origin_url);
1941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
196d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool IndexedDBFactory::IsDatabaseOpen(const GURL& origin_url,
197d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                                      const base::string16& name) const {
198d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
199d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return !!database_map_.count(IndexedDBDatabase::Identifier(origin_url, name));
200d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)}
201d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
202d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool IndexedDBFactory::IsBackingStoreOpen(const GURL& origin_url) const {
2031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return backing_store_map_.find(origin_url) != backing_store_map_.end();
2041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
206d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool IndexedDBFactory::IsBackingStorePendingClose(const GURL& origin_url)
207d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    const {
208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  IndexedDBBackingStoreMap::const_iterator it =
209a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      backing_store_map_.find(origin_url);
210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (it == backing_store_map_.end())
211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return false;
212a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return it->second->close_timer()->IsRunning();
213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
214a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_refptr<IndexedDBBackingStore> IndexedDBFactory::OpenBackingStore(
2161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const GURL& origin_url,
217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const base::FilePath& data_directory,
218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    blink::WebIDBDataLoss* data_loss,
2190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    std::string* data_loss_message,
22068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    bool* disk_full) {
221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const bool open_in_memory = data_directory.empty();
222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  IndexedDBBackingStoreMap::iterator it2 = backing_store_map_.find(origin_url);
22458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (it2 != backing_store_map_.end()) {
22558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    it2->second->close_timer()->Stop();
22658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return it2->second;
22758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<IndexedDBBackingStore> backing_store;
230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (open_in_memory) {
2311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    backing_store = IndexedDBBackingStore::OpenInMemory(origin_url);
232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
2330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    backing_store = IndexedDBBackingStore::Open(origin_url,
2340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                                data_directory,
2350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                                data_loss,
2360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                                data_loss_message,
2370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                                disk_full);
238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (backing_store.get()) {
2411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    backing_store_map_[origin_url] = backing_store;
242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // If an in-memory database, bind lifetime to this factory instance.
243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (open_in_memory)
244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      session_only_backing_stores_.insert(backing_store);
245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // All backing stores associated with this factory should be of the same
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // type.
248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(session_only_backing_stores_.empty() || open_in_memory);
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return backing_store;
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return 0;
254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBFactory::Open(
257a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& name,
258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 version,
259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 transaction_id,
260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBCallbacks> callbacks,
261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
2621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const GURL& origin_url,
263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const base::FilePath& data_directory) {
264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBFactory::Open");
265424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_refptr<IndexedDBDatabase> database;
2661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  IndexedDBDatabase::Identifier unique_identifier(origin_url, name);
267424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier);
268f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  blink::WebIDBDataLoss data_loss =
269f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      blink::WebIDBDataLossNone;
2700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  std::string data_loss_message;
27168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bool disk_full = false;
272d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  bool was_open = (it != database_map_.end());
273d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (!was_open) {
2741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    scoped_refptr<IndexedDBBackingStore> backing_store =
2750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        OpenBackingStore(origin_url,
2760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                         data_directory,
2770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                         &data_loss,
2780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                         &data_loss_message,
2790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                         &disk_full);
280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (!backing_store) {
28168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (disk_full) {
28268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        callbacks->OnError(
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionQuotaError,
28468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                   ASCIIToUTF16(
28568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                       "Encountered full disk while opening "
28668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                       "backing store for indexedDB.open.")));
28768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        return;
28868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks->OnError(IndexedDBDatabaseError(
290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          blink::WebIDBDatabaseExceptionUnknownError,
291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          ASCIIToUTF16(
292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              "Internal error opening backing store for indexedDB.open.")));
293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
296424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    database =
297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        IndexedDBDatabase::Create(name, backing_store, this, unique_identifier);
298424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (!database) {
299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks->OnError(IndexedDBDatabaseError(
300f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          blink::WebIDBDatabaseExceptionUnknownError,
301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          ASCIIToUTF16(
302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              "Internal error creating database backend for indexedDB.open.")));
303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
306424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    database = it->second;
307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3090f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  database->OpenConnection(callbacks,
3100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                           database_callbacks,
3110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                           transaction_id,
3120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                           version,
3130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                           data_loss,
3140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                           data_loss_message);
315d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
316d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (!was_open && database->ConnectionCount() > 0)
317d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    database_map_[unique_identifier] = database;
318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
320ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstd::vector<IndexedDBDatabase*> IndexedDBFactory::GetOpenDatabasesForOrigin(
3211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const GURL& origin_url) const {
322ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  std::vector<IndexedDBDatabase*> result;
323424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  for (IndexedDBDatabaseMap::const_iterator it = database_map_.begin();
324424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)       it != database_map_.end();
325424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)       ++it) {
3261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (it->first.first == origin_url)
327ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      result.push_back(it->second.get());
328ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
329ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return result;
330ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
331ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace content
333