1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CONTENT_BROWSER_DOM_STORAGE_DOM_STORAGE_NAMESPACE_H_
6#define CONTENT_BROWSER_DOM_STORAGE_DOM_STORAGE_NAMESPACE_H_
7
8#include <map>
9#include <vector>
10
11#include "base/basictypes.h"
12#include "base/files/file_path.h"
13#include "base/memory/ref_counted.h"
14#include "base/strings/nullable_string16.h"
15#include "content/common/content_export.h"
16#include "content/public/browser/session_storage_namespace.h"
17#include "url/gurl.h"
18
19namespace content {
20
21class DOMStorageArea;
22class DOMStorageContextImpl;
23class DOMStorageTaskRunner;
24class SessionStorageDatabase;
25
26// Container for the set of per-origin Areas.
27// See class comments for DOMStorageContextImpl for a larger overview.
28class CONTENT_EXPORT DOMStorageNamespace
29    : public base::RefCountedThreadSafe<DOMStorageNamespace> {
30 public:
31  // Option for PurgeMemory.
32  enum PurgeOption {
33    // Purge unopened areas only.
34    PURGE_UNOPENED,
35
36    // Purge aggressively, i.e. discard cache even for areas that have
37    // non-zero open count.
38    PURGE_AGGRESSIVE,
39  };
40
41  // Constructor for a LocalStorage namespace with id of 0
42  // and an optional backing directory on disk.
43  DOMStorageNamespace(const base::FilePath& directory,  // may be empty
44                      DOMStorageTaskRunner* task_runner);
45
46  // Constructor for a SessionStorage namespace with a non-zero id and an
47  // optional backing on disk via |session_storage_database| (may be NULL).
48  DOMStorageNamespace(int64 namespace_id,
49                      const std::string& persistent_namespace_id,
50                      SessionStorageDatabase* session_storage_database,
51                      DOMStorageTaskRunner* task_runner);
52
53  int64 namespace_id() const { return namespace_id_; }
54  const std::string& persistent_namespace_id() const {
55    return persistent_namespace_id_;
56  }
57
58  // Returns the storage area for the given origin,
59  // creating instance if needed. Each call to open
60  // must be balanced with a call to CloseStorageArea.
61  DOMStorageArea* OpenStorageArea(const GURL& origin);
62  void CloseStorageArea(DOMStorageArea* area);
63
64  // Returns the area for |origin| if it's open, otherwise NULL.
65  DOMStorageArea* GetOpenStorageArea(const GURL& origin);
66
67  // Creates a clone of |this| namespace including
68  // shallow copies of all contained areas.
69  // Should only be called for session storage namespaces.
70  DOMStorageNamespace* Clone(int64 clone_namespace_id,
71                             const std::string& clone_persistent_namespace_id);
72
73  // Creates an alias of |this| namespace.
74  // Should only be called for session storage namespaces.
75  DOMStorageNamespace* CreateAlias(int64 alias_namespace_id);
76
77  void DeleteLocalStorageOrigin(const GURL& origin);
78  void DeleteSessionStorageOrigin(const GURL& origin);
79  void PurgeMemory(PurgeOption purge);
80  void Shutdown();
81
82  unsigned int CountInMemoryAreas() const;
83
84  void AddTransactionLogProcessId(int process_id);
85  void RemoveTransactionLogProcessId(int process_id);
86  SessionStorageNamespace::MergeResult Merge(
87      bool actually_merge,
88      int process_id,
89      DOMStorageNamespace* other,
90      DOMStorageContextImpl* context);
91  DOMStorageNamespace* alias_master_namespace() {
92    return alias_master_namespace_.get();
93  }
94  int num_aliases() const { return num_aliases_; }
95  bool ready_for_deletion_pending_aliases() const {
96    return ready_for_deletion_pending_aliases_; }
97  void set_ready_for_deletion_pending_aliases(bool value) {
98    ready_for_deletion_pending_aliases_ = value;
99  }
100  bool must_persist_at_shutdown() const { return must_persist_at_shutdown_; }
101  void set_must_persist_at_shutdown(bool value) {
102    must_persist_at_shutdown_ = value;
103  }
104
105  enum LogType {
106    TRANSACTION_READ,
107    TRANSACTION_WRITE,
108    TRANSACTION_REMOVE,
109    TRANSACTION_CLEAR
110  };
111
112  struct CONTENT_EXPORT TransactionRecord {
113    LogType transaction_type;
114    GURL origin;
115    GURL page_url;
116    base::string16 key;
117    base::NullableString16 value;
118    TransactionRecord();
119    ~TransactionRecord();
120  };
121
122  void AddTransaction(int process_id, const TransactionRecord& transaction);
123  bool IsLoggingRenderer(int process_id);
124  // Decrements the count of aliases owned by the master, and returns true
125  // if the new count is 0.
126  bool DecrementMasterAliasCount();
127
128 private:
129  friend class base::RefCountedThreadSafe<DOMStorageNamespace>;
130
131  // Struct to hold references to our contained areas and
132  // to keep track of how many tabs have a given area open.
133  struct AreaHolder {
134    scoped_refptr<DOMStorageArea> area_;
135    int open_count_;
136    AreaHolder();
137    AreaHolder(DOMStorageArea* area, int count);
138    ~AreaHolder();
139  };
140  typedef std::map<GURL, AreaHolder> AreaMap;
141
142  struct TransactionData {
143    bool max_log_size_exceeded;
144    std::vector<TransactionRecord> log;
145    TransactionData();
146    ~TransactionData();
147  };
148
149  ~DOMStorageNamespace();
150
151  // Returns a pointer to the area holder in our map or NULL.
152  AreaHolder* GetAreaHolder(const GURL& origin);
153
154  // Switches the current alias DOM storage namespace to a new alias master.
155  void SwitchToNewAliasMaster(DOMStorageNamespace* new_master,
156                              DOMStorageContextImpl* context);
157
158  int64 namespace_id_;
159  std::string persistent_namespace_id_;
160  base::FilePath directory_;
161  AreaMap areas_;
162  scoped_refptr<DOMStorageTaskRunner> task_runner_;
163  scoped_refptr<SessionStorageDatabase> session_storage_database_;
164  std::map<int, TransactionData*> transactions_;
165  int num_aliases_;
166  scoped_refptr<DOMStorageNamespace> alias_master_namespace_;
167  DOMStorageNamespace* old_master_for_close_area_;
168  // Indicates whether we have already decremented |num_aliases_| for this
169  // namespace in its alias master. We may only decrement it once, and around
170  // deletion, this instance will stick around a bit longer until its refcount
171  // drops to 0. Therefore, we want to make sure we don't decrement the master's
172  // alias count a second time.
173  bool master_alias_count_decremented_;
174  // This indicates, for an alias master, that the master itself is ready
175  // for deletion, but there are aliases outstanding that we have to wait for
176  // before we can start cleaning up the master.
177  bool ready_for_deletion_pending_aliases_;
178  bool must_persist_at_shutdown_;
179};
180
181}  // namespace content
182
183
184#endif  // CONTENT_BROWSER_DOM_STORAGE_DOM_STORAGE_NAMESPACE_H_
185