sqlite_cursor.h revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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 CHROME_BROWSER_HISTORY_ANDROID_SQLITE_CURSOR_H_
6#define CHROME_BROWSER_HISTORY_ANDROID_SQLITE_CURSOR_H_
7
8#include <jni.h>
9#include <vector>
10
11#include "base/android/scoped_java_ref.h"
12#include "base/basictypes.h"
13#include "base/gtest_prod_util.h"
14#include "base/memory/scoped_ptr.h"
15#include "base/strings/string16.h"
16#include "base/synchronization/waitable_event.h"
17#include "base/task/cancelable_task_tracker.h"
18#include "chrome/browser/history/android/android_history_provider_service.h"
19#include "components/favicon_base/favicon_callback.h"
20#include "components/history/core/browser/history_types.h"
21
22class FaviconService;
23
24// This class is JNI implementation of
25// org.chromium.chrome.database.SqliteCursor, it uses the AndroidStatement to
26// iterate among the result rows. This is not thread safe, all methods should
27// be called from the same non-UI thread which typical is the Java thread.
28//
29// This class can not be in history namespace because the class name has to
30// match to the generated sqlite_cursor_jni.h.
31class SQLiteCursor {
32 public:
33  // Mapping to the column type definitions in java.sql.Types.
34  enum JavaColumnType {
35    BLOB = 2004,
36    LONG_VAR_CHAR = -1,
37    NULL_TYPE = 0,
38    NUMERIC = 2,
39    DOUBLE = 8,
40  };
41
42  // This class is intended to be used only in unit tests.
43  //
44  // There are 2 threads in unit test, one is the UI thread, another is the DB
45  // thread, after the task posted into UI thread, the MessageLoop needs to run
46  // to execute the task. The OnPostMoveToTask() and the OnPostGetFaviconTask()
47  // give unit tests a chance to run the message loop before event_.Wait is
48  // invoked, The OnGetMoveToResult() and OnGetFaviconResult() is used to notify
49  // the test observer in the UI thread when the task's result comes back, it
50  // calls MessageLoop::Quit() to exit the loop, then the event.Wait() is
51  // called. Basically, Two threads are used to simulate 3 threads' behavior
52  // here.
53  // The whole observer design is only for test purpose and should only be used
54  // in unit test.
55  class TestObserver {
56   public:
57    TestObserver();
58
59    // Notify the MoveTo task has been posted to UI thread.
60    virtual void OnPostMoveToTask() = 0;
61    // Notify the MoveTo result has been gotten in UI thread.
62    virtual void OnGetMoveToResult() = 0;
63    // Notify the GetFavicon task has been posted to UI thread.
64    virtual void OnPostGetFaviconTask() = 0;
65    // Notify the GetFavicon result has been gotten in UI thread.
66    virtual void OnGetFaviconResult() = 0;
67
68   protected:
69    virtual ~TestObserver();
70  };
71
72  // Returns org.chromium.chrome.SQLiteCursor java object by creating
73  // SQLitCursor native and java objects, then bind them together.
74  static base::android::ScopedJavaLocalRef<jobject> NewJavaSqliteCursor(
75      JNIEnv* env,
76      const std::vector<std::string>& column_names,
77      history::AndroidStatement* statement,
78      AndroidHistoryProviderService* service,
79      FaviconService* favicon_service);
80
81  static bool RegisterSqliteCursor(JNIEnv* env);
82
83  // JNI methods -----------------------------------------------------------
84
85  // Returns the result row count.
86  jint GetCount(JNIEnv* env, jobject obj);
87
88  // Returns the result's columns' name.
89  base::android::ScopedJavaLocalRef<jobjectArray> GetColumnNames(
90      JNIEnv* env,
91      jobject obj);
92
93  // Returns the given column value as jstring.
94  base::android::ScopedJavaLocalRef<jstring> GetString(JNIEnv* env,
95                                                       jobject obj,
96                                                       jint column);
97
98  // Returns the given column value as jlong.
99  jlong GetLong(JNIEnv* env, jobject obj, jint column);
100
101  // Returns the given column value as int.
102  jint GetInt(JNIEnv* env, jobject obj, jint column);
103
104  // Returns the given column value as double.
105  jdouble GetDouble(JNIEnv* env, jobject obj, jint column);
106
107  // Returns the given column value as jbyteArray.
108  base::android::ScopedJavaLocalRef<jbyteArray> GetBlob(JNIEnv* env,
109                                                        jobject obj,
110                                                        jint column);
111
112  // Return JNI_TRUE if the give column value is NULL, JNI_FALSE otherwise.
113  jboolean IsNull(JNIEnv* env, jobject obj, jint column);
114
115  // Moves the cursor to |pos|, returns new position.
116  // If the returned position is not equal to |pos|, then the cursor points to
117  // the last row.
118  jint MoveTo(JNIEnv* env, jobject obj, jint pos);
119
120  // Returns the type of column.
121  jint GetColumnType(JNIEnv* env, jobject obj, jint column);
122
123  // Called from Java to relase this object.
124  void Destroy(JNIEnv* env, jobject obj);
125
126 private:
127  FRIEND_TEST_ALL_PREFIXES(SQLiteCursorTest, Run);
128
129  // |column_names| is the column names of this cursor, the sequence of name
130  // should match the sql query's projection name.
131  // |statement| is query's statement which bound the variables. This class
132  // take the ownership of |statement|.
133  SQLiteCursor(const std::vector<std::string>& column_names,
134               history::AndroidStatement* statement,
135               AndroidHistoryProviderService* service,
136               FaviconService* favicon_service);
137
138  virtual ~SQLiteCursor();
139
140  // Destory SQLiteCursor object on UI thread. All cleanup need finish in UI
141  // thread.
142  void DestroyOnUIThread();
143
144  // This method is for testing only.
145  void set_test_observer(TestObserver* test_observer) {
146    test_observer_ = test_observer;
147  }
148
149  // Get Favicon from history backend.
150  bool GetFavicon(favicon_base::FaviconID id,
151                  std::vector<unsigned char>* image_data);
152
153  void GetFaviconForIDInUIThread(
154      favicon_base::FaviconID id,
155      const favicon_base::FaviconRawBitmapCallback& callback);
156
157  // The callback function of FaviconService::GetLargestRawFaviconForID().
158  void OnFaviconData(const favicon_base::FaviconRawBitmapResult& bitmap_result);
159
160  // The callback function of MoveTo().
161  void OnMoved(int pos);
162
163  JavaColumnType GetColumnTypeInternal(int column);
164
165  // Runs the MoveStatement on UI thread.
166  void RunMoveStatementOnUIThread(int pos);
167
168  // The current row position, '-1' means the position before the first one.
169  int position_;
170
171  base::WaitableEvent event_;
172
173  // The wrapped history::AndroidStatement.
174  history::AndroidStatement* statement_;
175
176  // Result set columns' name
177  const std::vector<std::string> column_names_;
178
179  AndroidHistoryProviderService* service_;
180
181  FaviconService* favicon_service_;
182
183  // Live on UI thread.
184  scoped_ptr<base::CancelableTaskTracker> tracker_;
185
186  // The count of result rows.
187  int count_;
188
189  // The favicon image.
190  favicon_base::FaviconRawBitmapResult favicon_bitmap_result_;
191
192  TestObserver* test_observer_;
193
194  DISALLOW_COPY_AND_ASSIGN(SQLiteCursor);
195};
196
197#endif  // CHROME_BROWSER_HISTORY_ANDROID_SQLITE_CURSOR_H_
198