summaryrefslogtreecommitdiffstats
path: root/webkit/dom_storage/dom_storage_area.h
blob: 7a179010ee57be1736c57c4f2a4c785c3c4da0fa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef WEBKIT_DOM_STORAGE_DOM_STORAGE_AREA_H_
#define WEBKIT_DOM_STORAGE_DOM_STORAGE_AREA_H_

#include "base/file_path.h"
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/nullable_string16.h"
#include "base/string16.h"
#include "googleurl/src/gurl.h"
#include "webkit/dom_storage/dom_storage_types.h"

namespace dom_storage {

class DomStorageDatabaseAdapter;
class DomStorageMap;
class DomStorageTaskRunner;
class SessionStorageDatabase;

// Container for a per-origin Map of key/value pairs potentially
// backed by storage on disk and lazily commits changes to disk.
// See class comments for DomStorageContext for a larger overview.
class DomStorageArea
    : public base::RefCountedThreadSafe<DomStorageArea> {

 public:
  static const FilePath::CharType kDatabaseFileExtension[];
  static FilePath DatabaseFileNameFromOrigin(const GURL& origin);
  static GURL OriginFromDatabaseFileName(const FilePath& file_name);

  // Local storage. Backed on disk if directory is nonempty.
  DomStorageArea(const GURL& origin,
                 const FilePath& directory,
                 DomStorageTaskRunner* task_runner);

  // Session storage. Backed on disk if |session_storage_backing| is not NULL.
  DomStorageArea(int64 namespace_id,
                 const std::string& persistent_namespace_id,
                 const GURL& origin,
                 SessionStorageDatabase* session_storage_backing,
                 DomStorageTaskRunner* task_runner);

  const GURL& origin() const { return origin_; }
  int64 namespace_id() const { return namespace_id_; }

  // Writes a copy of the current set of values in the area to the |map|.
  void ExtractValues(ValuesMap* map);

  unsigned Length();
  NullableString16 Key(unsigned index);
  NullableString16 GetItem(const string16& key);
  bool SetItem(const string16& key, const string16& value,
               NullableString16* old_value);
  bool RemoveItem(const string16& key, string16* old_value);
  bool Clear();

  DomStorageArea* ShallowCopy(
      int64 destination_namespace_id,
      const std::string& destination_persistent_namespace_id);

  bool HasUncommittedChanges() const;

  // Similar to Clear() but more optimized for just deleting
  // without raising events.
  void DeleteOrigin();

  // Frees up memory when possible. Typically, this method returns
  // the object to its just constructed state, however if uncommitted
  // changes are pending, it does nothing.
  void PurgeMemory();

  // Schedules the commit of any unsaved changes and enters a
  // shutdown state such that the value getters and setters will
  // no longer do anything.
  void Shutdown();

 private:
  friend class DomStorageAreaTest;
  FRIEND_TEST_ALL_PREFIXES(DomStorageAreaTest, DomStorageAreaBasics);
  FRIEND_TEST_ALL_PREFIXES(DomStorageAreaTest, BackingDatabaseOpened);
  FRIEND_TEST_ALL_PREFIXES(DomStorageAreaTest, TestDatabaseFilePath);
  FRIEND_TEST_ALL_PREFIXES(DomStorageAreaTest, CommitTasks);
  FRIEND_TEST_ALL_PREFIXES(DomStorageAreaTest, CommitChangesAtShutdown);
  FRIEND_TEST_ALL_PREFIXES(DomStorageAreaTest, DeleteOrigin);
  FRIEND_TEST_ALL_PREFIXES(DomStorageAreaTest, PurgeMemory);
  FRIEND_TEST_ALL_PREFIXES(DomStorageContextTest, PersistentIds);
  friend class base::RefCountedThreadSafe<DomStorageArea>;

  struct CommitBatch {
    bool clear_all_first;
    ValuesMap changed_values;
    CommitBatch();
    ~CommitBatch();
  };

  ~DomStorageArea();

  // If we haven't done so already and this is a local storage area,
  // will attempt to read any values for this origin currently
  // stored on disk.
  void InitialImportIfNeeded();

  // Post tasks to defer writing a batch of changed values to
  // disk on the commit sequence, and to call back on the primary
  // task sequence when complete.
  CommitBatch* CreateCommitBatchIfNeeded();
  void OnCommitTimer();
  void CommitChanges(const CommitBatch* commit_batch);
  void OnCommitComplete();

  void ShutdownInCommitSequence();

  int64 namespace_id_;
  std::string persistent_namespace_id_;
  GURL origin_;
  FilePath directory_;
  scoped_refptr<DomStorageTaskRunner> task_runner_;
  scoped_refptr<DomStorageMap> map_;
  scoped_ptr<DomStorageDatabaseAdapter> backing_;
  scoped_refptr<SessionStorageDatabase> session_storage_backing_;
  bool is_initial_import_done_;
  bool is_shutdown_;
  scoped_ptr<CommitBatch> commit_batch_;
  int commit_batches_in_flight_;
};

}  // namespace dom_storage

#endif  // WEBKIT_DOM_STORAGE_DOM_STORAGE_AREA_H_