1// Copyright (c) 2012 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_INDEXED_DB_INDEXED_DB_DISPATCHER_HOST_H_
6#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_DISPATCHER_HOST_H_
7
8#include <map>
9#include <string>
10#include <vector>
11
12#include "base/basictypes.h"
13#include "base/id_map.h"
14#include "base/memory/ref_counted.h"
15#include "content/browser/fileapi/chrome_blob_storage_context.h"
16#include "content/public/browser/browser_message_filter.h"
17#include "net/url_request/url_request_context_getter.h"
18#include "storage/browser/blob/blob_data_handle.h"
19#include "url/gurl.h"
20
21struct IndexedDBDatabaseMetadata;
22struct IndexedDBHostMsg_DatabaseCount_Params;
23struct IndexedDBHostMsg_DatabaseCreateIndex_Params;
24struct IndexedDBHostMsg_DatabaseCreateObjectStore_Params;
25struct IndexedDBHostMsg_DatabaseCreateTransaction_Params;
26struct IndexedDBHostMsg_DatabaseDeleteRange_Params;
27struct IndexedDBHostMsg_DatabaseGet_Params;
28struct IndexedDBHostMsg_DatabaseOpenCursor_Params;
29struct IndexedDBHostMsg_DatabasePut_Params;
30struct IndexedDBHostMsg_DatabaseSetIndexKeys_Params;
31struct IndexedDBHostMsg_FactoryDeleteDatabase_Params;
32struct IndexedDBHostMsg_FactoryGetDatabaseNames_Params;
33struct IndexedDBHostMsg_FactoryOpen_Params;
34
35namespace content {
36class IndexedDBConnection;
37class IndexedDBContextImpl;
38class IndexedDBCursor;
39class IndexedDBKey;
40class IndexedDBKeyPath;
41class IndexedDBKeyRange;
42struct IndexedDBDatabaseMetadata;
43
44// Handles all IndexedDB related messages from a particular renderer process.
45class IndexedDBDispatcherHost : public BrowserMessageFilter {
46 public:
47  // Only call the constructor from the UI thread.
48  IndexedDBDispatcherHost(int ipc_process_id,
49                          net::URLRequestContextGetter* request_context_getter,
50                          IndexedDBContextImpl* indexed_db_context,
51                          ChromeBlobStorageContext* blob_storage_context);
52  IndexedDBDispatcherHost(int ipc_process_id,
53                          net::URLRequestContext* request_context,
54                          IndexedDBContextImpl* indexed_db_context,
55                          ChromeBlobStorageContext* blob_storage_context);
56
57  static ::IndexedDBDatabaseMetadata ConvertMetadata(
58      const content::IndexedDBDatabaseMetadata& metadata);
59
60  // BrowserMessageFilter implementation.
61  virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
62  virtual void OnChannelClosing() OVERRIDE;
63  virtual void OnDestruct() const OVERRIDE;
64  virtual base::TaskRunner* OverrideTaskRunnerForMessage(
65      const IPC::Message& message) OVERRIDE;
66  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
67
68  void FinishTransaction(int64 host_transaction_id, bool committed);
69
70  // A shortcut for accessing our context.
71  IndexedDBContextImpl* Context() { return indexed_db_context_.get(); }
72  storage::BlobStorageContext* blob_storage_context() const {
73    return blob_storage_context_->context();
74  }
75
76  // IndexedDBCallbacks call these methods to add the results into the
77  // applicable map.  See below for more details.
78  int32 Add(IndexedDBCursor* cursor);
79  int32 Add(IndexedDBConnection* connection,
80            int32 ipc_thread_id,
81            const GURL& origin_url);
82
83  void RegisterTransactionId(int64 host_transaction_id, const GURL& origin_url);
84
85  IndexedDBCursor* GetCursorFromId(int32 ipc_cursor_id);
86
87  // These are called to map a 32-bit front-end (renderer-specific) transaction
88  // id to and from a back-end ("host") transaction id that encodes the process
89  // id in the high 32 bits. The mapping is host-specific and ids are validated.
90  int64 HostTransactionId(int64 transaction_id);
91  int64 RendererTransactionId(int64 host_transaction_id);
92
93  // These are called to decode a host transaction ID, for diagnostic purposes.
94  static uint32 TransactionIdToRendererTransactionId(int64 host_transaction_id);
95  static uint32 TransactionIdToProcessId(int64 host_transaction_id);
96
97  void HoldBlobDataHandle(const std::string& uuid,
98                          scoped_ptr<storage::BlobDataHandle> blob_data_handle);
99  void DropBlobDataHandle(const std::string& uuid);
100
101 private:
102  // Friends to enable OnDestruct() delegation.
103  friend class BrowserThread;
104  friend class base::DeleteHelper<IndexedDBDispatcherHost>;
105
106  // Used in nested classes.
107  typedef std::map<std::string, storage::BlobDataHandle*> BlobDataHandleMap;
108  typedef std::map<int64, int64> TransactionIDToDatabaseIDMap;
109  typedef std::map<int64, uint64> TransactionIDToSizeMap;
110  typedef std::map<int64, GURL> TransactionIDToURLMap;
111  typedef std::map<int32, GURL> WebIDBObjectIDToURLMap;
112
113  // IDMap for RefCounted types
114  template <typename RefCountedType>
115  class RefIDMap {
116   public:
117    typedef int32 KeyType;
118
119    RefIDMap() {}
120    ~RefIDMap() {}
121
122    KeyType Add(RefCountedType* data) {
123      return map_.Add(new scoped_refptr<RefCountedType>(data));
124    }
125
126    RefCountedType* Lookup(KeyType id) {
127      scoped_refptr<RefCountedType>* ptr = map_.Lookup(id);
128      if (ptr == NULL)
129        return NULL;
130      return ptr->get();
131    }
132
133    void Remove(KeyType id) { map_.Remove(id); }
134
135    void set_check_on_null_data(bool value) {
136      map_.set_check_on_null_data(value);
137    }
138
139   private:
140    IDMap<scoped_refptr<RefCountedType>, IDMapOwnPointer> map_;
141
142    DISALLOW_COPY_AND_ASSIGN(RefIDMap);
143  };
144
145  class DatabaseDispatcherHost {
146   public:
147    explicit DatabaseDispatcherHost(IndexedDBDispatcherHost* parent);
148    ~DatabaseDispatcherHost();
149
150    void CloseAll();
151    bool OnMessageReceived(const IPC::Message& message);
152
153    void OnCreateObjectStore(
154        const IndexedDBHostMsg_DatabaseCreateObjectStore_Params& params);
155    void OnDeleteObjectStore(int32 ipc_database_id,
156                             int64 transaction_id,
157                             int64 object_store_id);
158    void OnCreateTransaction(
159        const IndexedDBHostMsg_DatabaseCreateTransaction_Params&);
160    void OnClose(int32 ipc_database_id);
161    void OnVersionChangeIgnored(int32 ipc_database_id);
162    void OnDestroyed(int32 ipc_database_id);
163
164    void OnGet(const IndexedDBHostMsg_DatabaseGet_Params& params);
165    // OnPutWrapper starts on the IO thread so that it can grab BlobDataHandles
166    // before posting to the IDB TaskRunner for the rest of the job.
167    void OnPutWrapper(const IndexedDBHostMsg_DatabasePut_Params& params);
168    void OnPut(const IndexedDBHostMsg_DatabasePut_Params& params,
169               std::vector<storage::BlobDataHandle*> handles);
170    void OnSetIndexKeys(
171        const IndexedDBHostMsg_DatabaseSetIndexKeys_Params& params);
172    void OnSetIndexesReady(int32 ipc_database_id,
173                           int64 transaction_id,
174                           int64 object_store_id,
175                           const std::vector<int64>& ids);
176    void OnOpenCursor(const IndexedDBHostMsg_DatabaseOpenCursor_Params& params);
177    void OnCount(const IndexedDBHostMsg_DatabaseCount_Params& params);
178    void OnDeleteRange(
179        const IndexedDBHostMsg_DatabaseDeleteRange_Params& params);
180    void OnClear(int32 ipc_thread_id,
181                 int32 ipc_callbacks_id,
182                 int32 ipc_database_id,
183                 int64 transaction_id,
184                 int64 object_store_id);
185    void OnCreateIndex(
186        const IndexedDBHostMsg_DatabaseCreateIndex_Params& params);
187    void OnDeleteIndex(int32 ipc_database_id,
188                       int64 transaction_id,
189                       int64 object_store_id,
190                       int64 index_id);
191
192    void OnAbort(int32 ipc_database_id, int64 transaction_id);
193    void OnCommit(int32 ipc_database_id, int64 transaction_id);
194    IndexedDBDispatcherHost* parent_;
195    IDMap<IndexedDBConnection, IDMapOwnPointer> map_;
196    WebIDBObjectIDToURLMap database_url_map_;
197    TransactionIDToSizeMap transaction_size_map_;
198    TransactionIDToURLMap transaction_url_map_;
199    TransactionIDToDatabaseIDMap transaction_database_map_;
200
201   private:
202    DISALLOW_COPY_AND_ASSIGN(DatabaseDispatcherHost);
203  };
204
205  class CursorDispatcherHost {
206   public:
207    explicit CursorDispatcherHost(IndexedDBDispatcherHost* parent);
208    ~CursorDispatcherHost();
209
210    bool OnMessageReceived(const IPC::Message& message);
211
212    void OnAdvance(int32 ipc_object_store_id,
213                   int32 ipc_thread_id,
214                   int32 ipc_callbacks_id,
215                   uint32 count);
216    void OnContinue(int32 ipc_object_store_id,
217                    int32 ipc_thread_id,
218                    int32 ipc_callbacks_id,
219                    const IndexedDBKey& key,
220                    const IndexedDBKey& primary_key);
221    void OnPrefetch(int32 ipc_cursor_id,
222                    int32 ipc_thread_id,
223                    int32 ipc_callbacks_id,
224                    int n);
225    void OnPrefetchReset(int32 ipc_cursor_id,
226                         int used_prefetches,
227                         int unused_prefetches);
228    void OnDestroyed(int32 ipc_cursor_id);
229
230    IndexedDBDispatcherHost* parent_;
231    RefIDMap<IndexedDBCursor> map_;
232
233   private:
234    DISALLOW_COPY_AND_ASSIGN(CursorDispatcherHost);
235  };
236
237  virtual ~IndexedDBDispatcherHost();
238
239  // Helper templates.
240  template <class ReturnType>
241  ReturnType* GetOrTerminateProcess(IDMap<ReturnType, IDMapOwnPointer>* map,
242                                    int32 ipc_return_object_id);
243  template <class ReturnType>
244  ReturnType* GetOrTerminateProcess(RefIDMap<ReturnType>* map,
245                                    int32 ipc_return_object_id);
246
247  template <typename MapType>
248  void DestroyObject(MapType* map, int32 ipc_object_id);
249
250  // Message processing. Most of the work is delegated to the dispatcher hosts
251  // below.
252  void OnIDBFactoryGetDatabaseNames(
253      const IndexedDBHostMsg_FactoryGetDatabaseNames_Params& p);
254  void OnIDBFactoryOpen(const IndexedDBHostMsg_FactoryOpen_Params& p);
255
256  void OnIDBFactoryDeleteDatabase(
257      const IndexedDBHostMsg_FactoryDeleteDatabase_Params& p);
258
259  void OnAckReceivedBlobs(const std::vector<std::string>& uuids);
260  void OnPutHelper(const IndexedDBHostMsg_DatabasePut_Params& params,
261                   std::vector<storage::BlobDataHandle*> handles);
262
263  void ResetDispatcherHosts();
264
265  // The getter holds the context until OnChannelConnected() can be called from
266  // the IO thread, which will extract the net::URLRequestContext from it.
267  scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
268  net::URLRequestContext* request_context_;
269  scoped_refptr<IndexedDBContextImpl> indexed_db_context_;
270  scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
271
272  BlobDataHandleMap blob_data_handle_map_;
273
274  // Only access on IndexedDB thread.
275  scoped_ptr<DatabaseDispatcherHost> database_dispatcher_host_;
276  scoped_ptr<CursorDispatcherHost> cursor_dispatcher_host_;
277
278  // Used to set file permissions for blob storage.
279  int ipc_process_id_;
280
281  DISALLOW_IMPLICIT_CONSTRUCTORS(IndexedDBDispatcherHost);
282};
283
284}  // namespace content
285
286#endif  // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_DISPATCHER_HOST_H_
287