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_CHILD_INDEXED_DB_INDEXED_DB_DISPATCHER_H_
6#define CONTENT_CHILD_INDEXED_DB_INDEXED_DB_DISPATCHER_H_
7
8#include <map>
9#include <vector>
10
11#include "base/gtest_prod_util.h"
12#include "base/id_map.h"
13#include "base/memory/ref_counted.h"
14#include "base/strings/nullable_string16.h"
15#include "content/common/content_export.h"
16#include "ipc/ipc_sync_message_filter.h"
17#include "third_party/WebKit/public/platform/WebIDBCallbacks.h"
18#include "third_party/WebKit/public/platform/WebIDBCursor.h"
19#include "third_party/WebKit/public/platform/WebIDBDatabase.h"
20#include "third_party/WebKit/public/platform/WebIDBDatabaseCallbacks.h"
21#include "webkit/child/worker_task_runner.h"
22
23struct IndexedDBDatabaseMetadata;
24struct IndexedDBMsg_CallbacksSuccessCursorContinue_Params;
25struct IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params;
26struct IndexedDBMsg_CallbacksSuccessIDBCursor_Params;
27struct IndexedDBMsg_CallbacksUpgradeNeeded_Params;
28
29namespace WebKit {
30class WebData;
31}
32
33namespace content {
34class IndexedDBKey;
35class IndexedDBKeyPath;
36class IndexedDBKeyRange;
37class RendererWebIDBCursorImpl;
38class RendererWebIDBDatabaseImpl;
39class ThreadSafeSender;
40
41CONTENT_EXPORT extern const size_t kMaxIDBValueSizeInBytes;
42
43// Handle the indexed db related communication for this context thread - the
44// main thread and each worker thread have their own copies.
45class CONTENT_EXPORT IndexedDBDispatcher
46    : public webkit_glue::WorkerTaskRunner::Observer {
47 public:
48  // Constructor made public to allow RenderThreadImpl to own a copy without
49  // failing a NOTREACHED in ThreadSpecificInstance in tests that instantiate
50  // two copies of RenderThreadImpl on the same thread.  Everyone else probably
51  // wants to use ThreadSpecificInstance().
52  explicit IndexedDBDispatcher(ThreadSafeSender* thread_safe_sender);
53  virtual ~IndexedDBDispatcher();
54
55  // |thread_safe_sender| needs to be passed in because if the call leads to
56  // construction it will be needed.
57  static IndexedDBDispatcher* ThreadSpecificInstance(
58      ThreadSafeSender* thread_safe_sender);
59
60  // webkit_glue::WorkerTaskRunner::Observer implementation.
61  virtual void OnWorkerRunLoopStopped() OVERRIDE;
62
63  static WebKit::WebIDBMetadata ConvertMetadata(
64      const IndexedDBDatabaseMetadata& idb_metadata);
65
66  void OnMessageReceived(const IPC::Message& msg);
67  bool Send(IPC::Message* msg);
68
69  void RequestIDBFactoryGetDatabaseNames(
70      WebKit::WebIDBCallbacks* callbacks,
71      const std::string& database_identifier);
72
73  void RequestIDBFactoryOpen(
74      const string16& name,
75      int64 version,
76      int64 transaction_id,
77      WebKit::WebIDBCallbacks* callbacks,
78      WebKit::WebIDBDatabaseCallbacks* database_callbacks,
79      const std::string& database_identifier);
80
81  void RequestIDBFactoryDeleteDatabase(const string16& name,
82                                       WebKit::WebIDBCallbacks* callbacks,
83                                       const std::string& database_identifier);
84
85  void RequestIDBCursorAdvance(unsigned long count,
86                               WebKit::WebIDBCallbacks* callbacks_ptr,
87                               int32 ipc_cursor_id);
88
89  virtual void RequestIDBCursorContinue(const IndexedDBKey& key,
90                                        WebKit::WebIDBCallbacks* callbacks_ptr,
91                                        int32 ipc_cursor_id);
92
93  virtual void RequestIDBCursorPrefetch(int n,
94                                        WebKit::WebIDBCallbacks* callbacks_ptr,
95                                        int32 ipc_cursor_id);
96
97  void RequestIDBCursorPrefetchReset(int used_prefetches,
98                                     int unused_prefetches,
99                                     int32 ipc_cursor_id);
100
101  void RequestIDBDatabaseClose(int32 ipc_database_id,
102                               int32 ipc_database_callbacks_id);
103
104  void RequestIDBDatabaseCreateTransaction(
105      int32 ipc_database_id,
106      int64 transaction_id,
107      WebKit::WebIDBDatabaseCallbacks* database_callbacks_ptr,
108      WebKit::WebVector<long long> object_store_ids,
109      unsigned short mode);
110
111  void RequestIDBDatabaseGet(int32 ipc_database_id,
112                             int64 transaction_id,
113                             int64 object_store_id,
114                             int64 index_id,
115                             const IndexedDBKeyRange& key_range,
116                             bool key_only,
117                             WebKit::WebIDBCallbacks* callbacks);
118
119  void RequestIDBDatabasePut(
120      int32 ipc_database_id,
121      int64 transaction_id,
122      int64 object_store_id,
123      const WebKit::WebData& value,
124      const IndexedDBKey& key,
125      WebKit::WebIDBDatabase::PutMode put_mode,
126      WebKit::WebIDBCallbacks* callbacks,
127      const WebKit::WebVector<long long>& index_ids,
128      const WebKit::WebVector<WebKit::WebVector<WebKit::WebIDBKey> >&
129          index_keys);
130
131  void RequestIDBDatabaseOpenCursor(int32 ipc_database_id,
132                                    int64 transaction_id,
133                                    int64 object_store_id,
134                                    int64 index_id,
135                                    const IndexedDBKeyRange& key_range,
136                                    unsigned short direction,
137                                    bool key_only,
138                                    WebKit::WebIDBDatabase::TaskType task_type,
139                                    WebKit::WebIDBCallbacks* callbacks);
140
141  void RequestIDBDatabaseCount(int32 ipc_database_id,
142                               int64 transaction_id,
143                               int64 object_store_id,
144                               int64 index_id,
145                               const IndexedDBKeyRange& key_range,
146                               WebKit::WebIDBCallbacks* callbacks);
147
148  void RequestIDBDatabaseDeleteRange(int32 ipc_database_id,
149                                     int64 transaction_id,
150                                     int64 object_store_id,
151                                     const IndexedDBKeyRange& key_range,
152                                     WebKit::WebIDBCallbacks* callbacks);
153
154  void RequestIDBDatabaseClear(int32 ipc_database_id,
155                               int64 transaction_id,
156                               int64 object_store_id,
157                               WebKit::WebIDBCallbacks* callbacks);
158
159  virtual void CursorDestroyed(int32 ipc_cursor_id);
160  void DatabaseDestroyed(int32 ipc_database_id);
161
162 private:
163  FRIEND_TEST_ALL_PREFIXES(IndexedDBDispatcherTest, ValueSizeTest);
164
165  static int32 CurrentWorkerId() {
166    return webkit_glue::WorkerTaskRunner::Instance()->CurrentWorkerId();
167  }
168
169  template <typename T>
170  void init_params(T& params, WebKit::WebIDBCallbacks* callbacks_ptr) {
171    scoped_ptr<WebKit::WebIDBCallbacks> callbacks(callbacks_ptr);
172    params.ipc_thread_id = CurrentWorkerId();
173    params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
174  }
175
176  // IDBCallback message handlers.
177  void OnSuccessIDBDatabase(int32 ipc_thread_id,
178                            int32 ipc_callbacks_id,
179                            int32 ipc_database_callbacks_id,
180                            int32 ipc_object_id,
181                            const IndexedDBDatabaseMetadata& idb_metadata);
182  void OnSuccessIndexedDBKey(int32 ipc_thread_id,
183                             int32 ipc_callbacks_id,
184                             const IndexedDBKey& key);
185
186  void OnSuccessOpenCursor(
187      const IndexedDBMsg_CallbacksSuccessIDBCursor_Params& p);
188  void OnSuccessCursorContinue(
189      const IndexedDBMsg_CallbacksSuccessCursorContinue_Params& p);
190  void OnSuccessCursorPrefetch(
191      const IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params& p);
192  void OnSuccessStringList(int32 ipc_thread_id,
193                           int32 ipc_callbacks_id,
194                           const std::vector<string16>& value);
195  void OnSuccessValue(int32 ipc_thread_id,
196                      int32 ipc_callbacks_id,
197                      const std::string& value);
198  void OnSuccessValueWithKey(int32 ipc_thread_id,
199                             int32 ipc_callbacks_id,
200                             const std::string& value,
201                             const IndexedDBKey& primary_key,
202                             const IndexedDBKeyPath& key_path);
203  void OnSuccessInteger(int32 ipc_thread_id,
204                        int32 ipc_callbacks_id,
205                        int64 value);
206  void OnSuccessUndefined(int32 ipc_thread_id, int32 ipc_callbacks_id);
207  void OnError(int32 ipc_thread_id,
208               int32 ipc_callbacks_id,
209               int code,
210               const string16& message);
211  void OnIntBlocked(int32 ipc_thread_id,
212                    int32 ipc_callbacks_id,
213                    int64 existing_version);
214  void OnUpgradeNeeded(const IndexedDBMsg_CallbacksUpgradeNeeded_Params& p);
215  void OnAbort(int32 ipc_thread_id,
216               int32 ipc_database_id,
217               int64 transaction_id,
218               int code,
219               const string16& message);
220  void OnComplete(int32 ipc_thread_id,
221                  int32 ipc_database_id,
222                  int64 transaction_id);
223  void OnForcedClose(int32 ipc_thread_id, int32 ipc_database_id);
224  void OnIntVersionChange(int32 ipc_thread_id,
225                          int32 ipc_database_id,
226                          int64 old_version,
227                          int64 new_version);
228
229  // Reset cursor prefetch caches for all cursors except exception_cursor_id.
230  void ResetCursorPrefetchCaches(int32 ipc_exception_cursor_id = -1);
231
232  scoped_refptr<ThreadSafeSender> thread_safe_sender_;
233
234  // Careful! WebIDBCallbacks wraps non-threadsafe data types. It must be
235  // destroyed and used on the same thread it was created on.
236  IDMap<WebKit::WebIDBCallbacks, IDMapOwnPointer> pending_callbacks_;
237  IDMap<WebKit::WebIDBDatabaseCallbacks, IDMapOwnPointer>
238      pending_database_callbacks_;
239
240  // Map from cursor id to RendererWebIDBCursorImpl.
241  std::map<int32, RendererWebIDBCursorImpl*> cursors_;
242
243  std::map<int32, RendererWebIDBDatabaseImpl*> databases_;
244
245  DISALLOW_COPY_AND_ASSIGN(IndexedDBDispatcher);
246};
247
248}  // namespace content
249
250#endif  // CONTENT_CHILD_INDEXED_DB_INDEXED_DB_DISPATCHER_H_
251